Board index » cppbuilder » Problem with Form1's position and size at runtime...

Problem with Form1's position and size at runtime...


2003-12-14 06:15:43 PM
cppbuilder77
Hi,
This is a simple and useful fragment of code for setting Form1's window
position and size at runtime. It could help if you want to allow users to
configure (*.INI) how they want to appear the MainForm next time they
start the application.
// Add this code as global in Unit1.cpp for testing...
// (it's easier for this example)
enum WindowPositionAndSize
{
wpHardcoded, // Show Form1 with hardcoded Height and Width but centered
on desktop
wpLastUsed, // Show Form1 with last used position and size
wpMaximized // Show Form1 maximized
} MyChoice = wpMaximized; // Change to other values for testing...
// Imagine that we got these from INI ...
int LastLeft = 50;
int LastTop = 50;
int LastHeight = 200;
int LastWidth = 300;
// This is our desired hardcoded Form1's size
int HardcodedHeight = 200;
int HardcodedWidth = 300;
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
switch ( MyChoice )
{
case wpHardcoded:
Left = ( Screen->Width - HardcodedWidth ) / 2;
Top = ( Screen->Height - HardcodedHeight ) / 2;
Width = HardcodedWidth;
Height = HardcodedHeight;
break;
case wpLastUsed:
Left = LastLeft;
Top = LastTop;
Width = LastWidth;
Height = LastHeight;
break;
case wpMaximized:
// Do this (same as wpHardcoded) to avoid
// ... design time Form1's Size when restored
// I think it should restore to wpHardcoded
Left = ( Screen->Width - HardcodedWidth ) / 2;
Top = ( Screen->Height - HardcodedHeight ) / 2;
Width = HardcodedWidth;
Height = HardcodedHeight;
WindowState = wsMaximized;
break;
}
QUESTION:
This code works fine in this clean situation and I followed this approach in
my app. But
in some of my (complex) projects some strange things happens when I try to
Maximize
(this can be viewed better on some slower machines).
These steps are executed very fast, but I managed to see the hronology:
1) The Form1 realy maximizes for a second
2) I see the client arrea (MDI frame below main menu and toolbar) that has
not maximized
(stayed I think in design time size).The same is if app is SDI but then you
cannot see the frame.
3) Controls on the Form1 stays fixed on their disign time sizes though NONE
OF THEM
are Aligned to 'alNone'. They are aligned as necessary (alLeft, alTop,
alBottom, alClient).
4) The same controls I mentioned that stayed at design time suddenly aligns
to Maximized state
(the state that I wanted to be)
5) Then, Form1 returns to its designed size (Height, Weight), but with Left
= Top = 0;
6) The gadged in the Form1's Caption Bar has left in the 'Restore' state.
The Form1 obviously
think it's maximized. That means my Form1 is restored and I can only Restore
it through the
gadget :) I cannot even resize it.
What I did wrong?
I suspected on FormResize() that takes care of some metrics of Panels which
can be moved
by Splitter, and some recursions that can be so produced.
I added some code like this:
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
OnResize = NULL;
switch ( MyChoice )
{
// ...
}
OnResize = FormResize;
}
... but unfortunately the problem was not solved.
Strange thing is also that if I add this piece of code Form1 realy stayes
Maximized
but it's behaves ugly when you want to Restore it (it restores for a
milimetres).
case wpMaximized:
// This 4 lines are added...
Left = 0;
Top = 0;
Width = Screen->Width;
Height = Screen->Height;
Vladimir.
 
 

Re:Problem with Form1's position and size at runtime...

Vladimir Stefanovic wrote:
Quote
This is a simple and useful fragment of code for setting Form1's window
position and size at runtime.
Left = LastLeft;
Top = LastTop;
Width = LastWidth;
Height = LastHeight;
No that is not as usefull as you think.
Those four statements trigger four redraw events.
Start using SetBounds:
SetBounds( LastLeft, LastTop, LastWidth, LastHeight);
Please supply less code. This was so much to read, that
at the end confusion comes. Please first see if SetBounds helps.
Hans.
 

Re:Problem with Form1's position and size at runtime...

Vladimir Stefanovic wrote:
Quote
This is a simple and useful fragment of code for setting Form1's window
position and size at runtime.
case wpMaximized:

// Do this (same as wpHardcoded) to avoid
// ... design time Form1's Size when restored
// I think it should restore to wpHardcoded
Left = ( Screen->Width - HardcodedWidth ) / 2;
Top = ( Screen->Height - HardcodedHeight ) / 2;
Width = HardcodedWidth;
Height = HardcodedHeight;

WindowState = wsMaximized;
It makes no sence to first set Left, Top, Width and Height and
than make the WindowState wsMaximized. The only thing that
was needed here is the WindowState = wsMaximized statement.
Hans.
 

{smallsort}

Re:Problem with Form1's position and size at runtime...

"Vladimir Stefanovic" < XXXX@XXXXX.COM >wrote:
Quote
[...] I want also to control the positon where my form
is to be Restored for the first time.
Have a look in the win32.hlp file for the LockWindowUpdate API.
It might solve your visual problems.
~ JD
 

Re:Problem with Form1's position and size at runtime...

Quote
>Left = LastLeft;
>Top = LastTop;
>Width = LastWidth;
>Height = LastHeight;
No that is not as usefull as you think.
Those four statements trigger four redraw events.
Start using SetBounds:
SetBounds( LastLeft, LastTop, LastWidth, LastHeight);
I accept the note. One redraw event is better than four particulary
when you have lots of components on the Form.
Quote
It makes no sence to first set Left, Top, Width and Height and
than make the WindowState wsMaximized. The only thing that
was needed here is the WindowState = wsMaximized statement.
No. It do has sense. I want also to control the positon where my form
is to be Restored for the first time. I think it's correct to be at least
centered,
and I cannot in advance know what screen resolution the user has.
Vladimir.
 

Re:Problem with Form1's position and size at runtime...

I solved the problem! I replaced all code from:
void __fastcall TInitialForm::FormActivate(TObject *Sender)
{
// Moved to FormShow
// GoActivateForm();
}
to:
void __fastcall TInitialForm::FormShow(TObject *Sender)
{
GoActivateForm();
}
... and everything went ok with maximizing!
Function GoActivateForm() in some conditions was intended
to show an aditional information form, for example "...This app
was no longer associated to file extension... if you wish to...".
Unfortunately, this dialog has no longer the Form1 (main form)
in the backgroud if shown. Is there a way to code an event that
occures immediately after FormActivate (AfterOnActivate)?
Vladimir?
 

Re:Problem with Form1's position and size at runtime...

I managed to find what statement hasn't allowed Form1 to maximize!
That was 'Panel1->Visible = true' located in FormActivate.
This is the complete code if someone is interested.
Add 'Panel1' on 'Form1' and set Align = 'alClient'
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
// For some reason I wanted to hide all contents of Panel1 before
FormActivation.
Panel1->Visible = false;
WindowState = wsMaximized;
}
void __fastcall TForm1::FormActivate(TObject *Sender)
{
// This statement is problematic and doesn't allow the Form1 to maxime!
Panel1->Visible = true;
}
 

Re:Problem with Form1's position and size at runtime...

"Vladimir Stefanovic" < XXXX@XXXXX.COM >wrote:
Quote
[...] Is there a way to code an event that occures
immediately after FormActivate
You could try sending a custom message:
--- Unit1.h ---
#define APPWM_AFTER_ACTIVATE (WM_APP + 100)
#define AFTER_ACTIVATE_MAGIC_NUMBER 0xAFAFAFAF
#pragma pack( push, 1 )
TWMAfterActivate
{
unsigned Msg;
unsigned MagicNum;
int Result;
};
#pragma pack( pop )
class TForm1 : public TForm
{
__published:
void __fastcall Button1Click(TObject *Sender);
private:
void __fastcall AfterActivate(TWMAfterActivate &Message);
//...
public:
//...
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(APPWM_AFTER_ACTIVATE, TWMAfterActivate, AfterActivate)
END_MESSAGE_MAP(TForm)
};
--- Unit.cpp ---
void __fastcall TForm1::FormActivate(TObject *Sender)
{
PostMessage(Handle, APPWM_AFTER_ACTIVATE, AFTER_ACTIVATE_MAGIC_NUMBER, NULL );
}
void __fastcall TForm1::AfterActivate(TWMAfterActivate &Message)
{
if( Message.MagicNum == AFTER_ACTIVATE_MAGIC_NUMBER )
{
// do something
Message.Result = TRUE;
}
else TForm::Dispatch( &Message );
}
void __fastcall TForm1::FormShow(TObject *Sender)
{
// just make sure that your custom message gets processed before the OnShow executes
Application->ProcessMessages();
GoActivateForm();
}
~ JD
 

Re:Problem with Form1's position and size at runtime...

"Vladimir Stefanovic" < XXXX@XXXXX.COM >wrote:
Quote
[...] Thanks for the code,
Thank Gambit. I got it from him :-D but I did make some changes
to make it more readable for your purposes.
~ JD
 

Re:Problem with Form1's position and size at runtime...

Quote
You could try sending a custom message:

--- Unit1.h ---
#define APPWM_AFTER_ACTIVATE (WM_APP + 100)
#define AFTER_ACTIVATE_MAGIC_NUMBER 0xAFAFAFAF
[...]
JD, Thanks for the code, all use it very gladly!
Vladimir.