Board index » cppbuilder » ZOrder of Forms

ZOrder of Forms


2006-04-26 02:18:47 AM
cppbuilder36
Hi
I'm struggling a bit with the window ZOrder in my app.
The problem is that I need to display a window non-modally but this window
occasionally shows modal forms.
The non-modal form also must have a task bar button so that the user can
easily switch between the main screen and the non-modal form.
So to recap:
Form1 (Main Form with taskbar button)
Form2 (Non-Modal Form with taskbar button)
Form3 (Modal Form called from Form2)
If the user has all three screens open and is working in Form3 then the
ZOrder (visually) looks like
Form1
Form2
Form3
and there are two buttons on the task bar (Form1 , Form2).
If the user swaps to another application and then back to mine by clicking
on the taskbar buttons all works well if he uses Form1's taskbar button,
i.e. the forms are still 'stacked' in the same order as when he left, but if
he clicks on Form2's taskbar button then Form2 (which is disabled because
Form3 is modal) comes to the front and hence the app appears to have locked
(clicking between the taskbar buttons does bring the forms back into the
'correct' order eventually).
i.e.
Form1
Form3
Form2
To see this in action create a new application with three forms, add a
button to form1 and 2.
In Form1::ButtonClick
Form2->Show();
In Form2::ButtonClick
Form3->ShowModal();
I use the following to create the taskbar button in form2
void __fastcall TForm2::CreateParams(TCreateParams &Params)
{
TForm::CreateParams(Params);
Params.ExStyle |= WS_EX_APPWINDOW;
}
Running the app and following the above and you should see the problem.
I think that a solution might be to somehow disable Form2 from reacting to
any clicks on it's taskbar button if it is disabled and instead pass the
message (or whatever) on to Form1's taskbar button.
An alternate solution was to remove the taskbar button of Form2 before
showing Form3, I tried using this:
long exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, exstyle & ~WS_EX_APPWINDOW);
But unfortunately this didn't work.
Anyone able to help?
Best regards
Chris
 
 

Re:ZOrder of Forms

"Chris" < XXXX@XXXXX.COM >wrote:
Quote

[...] but if he clicks on Form2's taskbar button then Form2
(which is disabled because Form3 is modal) comes to the
front
I'm sure that there are several ways to get what you want but
this worked for me:
//-------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
Application->OnActivate = AppActivate;
}
//-------------------------------------------------------------
__fastcall TForm1::~TForm1()
{
Application->OnActivate = NULL;
}
//-------------------------------------------------------------
void __fastcall TForm1::AppActivate(TObject *Sender)
{
if( Form3->Visible ) ::SetForegroundWindow( Form3->Handle );
}
//-------------------------------------------------------------
If you have other issues like dynamic allocation ect., you'll
have to work out the details.
~ JD
 

Re:ZOrder of Forms

"JD" < XXXX@XXXXX.COM >wrote in message
Quote

I'm sure that there are several ways to get what you want but
this worked for me:

//-------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
Application->OnActivate = AppActivate;
}
//-------------------------------------------------------------
__fastcall TForm1::~TForm1()
{
Application->OnActivate = NULL;
}
//-------------------------------------------------------------
void __fastcall TForm1::AppActivate(TObject *Sender)
{
if( Form3->Visible ) ::SetForegroundWindow( Form3->Handle );
}
//-------------------------------------------------------------

Hi JD
Thanks for the answer.
I don't think this will work fo rme though as the sample I posted was just
to reproduce the problem. I was really looking for a solution that was more
generic (i.e. didn't have to know what other forms might be visible etc) as
in my real app all the forms are created dynamically etc and I'm sure the
logic to try and keep everything working smoothly would be a nightmare.
I will see what others care to suggest and then see what works the best.
Thanks once again
Chris
 

{smallsort}

Re:ZOrder of Forms

"Chris" < XXXX@XXXXX.COM >wrote:
Quote

I don't think this will work fo rme though as the sample I
posted was just to reproduce the problem. I was really
looking for a solution that was more generic (i.e. didn't
have to know what other forms might be visible etc)
You should have included that information to begin with.
#include <vector>
std::vector<TForm*>vForms;
//-------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
Application->OnActivate = AppActivate;
Application->OnDeactivate = AppDeactivate;
}
//-------------------------------------------------------------
__fastcall TForm1::~TForm1()
{
Application->OnActivate = NULL;
Application->OnDeactivate = NULL;
}
//-------------------------------------------------------------
void __fastcall TForm1::AppDeactivate(TObject *Sender)
{
for( int x = 0; x < Screen->FormCount; ++x )
{
if( Screen->Forms[x]->Visible ) vForms.push_back( Screen->Forms[x] );
}
}
//-------------------------------------------------------------
void __fastcall TForm1::AppActivate(TObject *Sender)
{
for( int x = vForms.size() - 1; x>-1; --x )
{
::SetForegroundWindow( vForms[x]->Handle );
}
}
//-------------------------------------------------------------
~ JD
 

Re:ZOrder of Forms

"JD" < XXXX@XXXXX.COM >wrote:
Quote

I should add that if you have doubts about the reliability
of the sample, the Screen::Forms property maintaines the list
according to their ZOrder.
~ JD
 

Re:ZOrder of Forms

Hi JD
Thanks for the revised version. This is better but still has problems (if
just form1 and Form2 are showing, clicking on Form2's task bar button
results in incorrect zorder etc)
I will keep playing to see if I get anywhere, but I must confess that I have
added a 'Window List' menu item to my app and I may yet remove all task bar
buttons and simply let the user select the screen via the menu.
Thanks for looking all the same and for the pointers.
Chris