Many times after the Windows 98 era we have experienced that some dialogs lose their Z-Order and move back to the prior form.
For example:
Dialog1.Sh
For old versions of delphi (prior to Delphi 2007), on forms OTHER than your main form:
interface
TMyForm = Class(TForm)
protected
procedure CreateParams(var Para: TCreateParams); override;
end;
...
implementation
...
procedure TMyForm.CreateParams(var Para: TCreateParams);
begin
inherited;
Para.Style := Para.Style or WS_POPUP;
{ WinXP Window manager requires this for proper Z-Ordering }
// Para.WndParent:=GetActiveWindow;
Para.WndParent := Application.MainForm.Handle;
end;
For message boxes include MB_TOPMOST in your flags:
Application.MessageBox(PChar(amessage), PChar(atitle), otherflags or MB_TOPMOST);
A trick I've used recently was to apply these two lines of code during the creation of each form:
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or
WS_EX_APPWINDOW or WS_EX_TOPMOST);
SetWindowLong(Handle, GWL_HWNDPARENT, GetDesktopWindow);
Handle is the handle of the form (Form1.Handle). The WS_EX_APPWINDOW part makes each window appear on the task bar, remove it if you don't want that additional effect.
For my main form I use this line:
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or
WS_EX_TOPMOST);
I also use this function to help build my custom dialogs (I created a new function for each style of dialog - error, confirmation, etc.):
function CustomDlg(const AMessage : string; const ADlgType: TMsgDlgType;
const AButtons: TMsgDlgButtons; const ADefaultButton: TMsgDlgBtn) : TForm;
begin
Result := CreateMessageDialog(AMessage, ADlgType, AButtons, ADefaultButton);
with Result do
begin
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or
WS_EX_APPWINDOW or WS_EX_TOPMOST);
SetWindowLong(Handle, GWL_HWNDPARENT, GetDesktopwindow);
FormStyle := fsStayOnTop;
BringToFront;
end;
end;
The FormStyle := fsStayOnTop;
part is optional, of course, but I use it to make sure my confirmation and error dialogs are always visible to the user.
It seems like a bit of work but the net effect is that I no longer have to worry about forms accidentally hiding behind other forms.
That's what the PopupMode and PopupParent properties are for.
E.g., you can do:
Dialog1.PopupMode := pmExplicit;
Dialog1.PopupParent := self;
Dialog1.ShowModal;
This tells Windows the correct Z-order.
I looked at this page and the FAQ for half an hour and still can't find how to post a comment, so forgive me for this breach of protocol.
First of all I'd like to make clear that the poster, IMHO, is not using Windows 98. He writes "after Windows 98 era" which I understand means he is having this problem with Windows versions after 98.
As I am having this problem too (CB2009), I'd like to emphasize the poster's question "Is it Windows bug?", which I have not seen answered. If it's a Delphi/Builder bug, maybe there is a way to avoid it? I can't see how intercepting all potential dialogs is a workable solution, nor avoid using fsStayOnTop. I have a settings form that needs to stay on top of my main form, but the settings form can and will popup dialogs that under certain conditions will disappear under the settings form.
It would be very helpful if I would understand where the support of z-order goes wrong, as it may offer a clue on how to avoid it.