Proper handling of modal window "Minimize" behavior
Asked Answered
T

2

8

I have the following issue: we're building a rather large application (win32, Delphi 6 Enterprise). In several part of the application, modal windows are used, usually containing the detail of the selection of the main window.

We included a modification of the handling of the WM_SYSCOMMAND messages so that, if the window is modal, then a SW_SHOWMINNOACTIVE message will be sent to the application's main window. This causes the whole application to be minimized instead of just the modal form.

There is, however, an issue happening in a specific case: if the calling window is set to full screen, then upon restoration, the modal window will appear UNDER the (disabled) maximized main window (this seems to happen on Windows 7)

My problem is two fold:

First, I don't seem to get any syscommand message when the application is restored any more so I cannot introduce code to restore the Z-Order because I don't know where to put it. Second, it seems to me that, if the whole application is minimized, clicking on the app's button in the task bar should restore it in the same state, not with a modal window under it. Is there a way to fix that ?

Edit: we did some additional testing and it seems we can actually detect the problem in the WM_ACTIVATE handler for the main form. We can also identify the modal window at that stage. I cannot, however, find a way to restore it to the top of the Z-Order.

Edit2: here is the code that minimizes the application when the modal form is minimized:

procedure TfmGITForm.WMSysCommand(var Message: TWMSysCommand);
begin
  if (fsModal in FormState) or
      not Application.MainForm.Visible then
  begin
    case Message.CmdType of
      SC_MINIMIZE:
      begin
        ShowWindow(Application.Handle, SW_SHOWMINNOACTIVE);
      end;
      SC_RESTORE:
      begin
        ShowWindow(Application.Handle, SW_SHOWNORMAL);
        inherited;
      end;
    else
      inherited;
    end;    // case
  end
  else
    inherited;
end;

All our forms descend from that one.

Terrorist answered 10/6, 2011 at 8:3 Comment(11)
Which version of Delphi?Congratulation
Hmm, I recall similar issues with Delphi 6 that I think were improved in more recent Delphi releases through the introduction of the PopupParent property and its relatives. Others will no doubt be more au fait with the precise details.Congratulation
Could you expand on the sending of SW_SHOWMINNOACTIVE. Is this so that minimizing the modal form results in the whole app being minimized? If so try calling Application.Minimize instead.Congratulation
Another question: which window is the owner of modal window? I mean this in the sense of the window owner and not the VCL owner.Congratulation
@stephane What happens if you call Application.Minimize and Application.Restore instead of calling ShowWindow?Congratulation
I recently have made the same mistake, the correct case is case Message.CmdType and $FFF0 of. See remarks in WM_SYSCOMMAND.Gemagemara
@David Heffernan: I'm almost certain it's the hidden TApplication window. The caption is the one from the global TApplication instance, the class name is TApplication and the handle of returned by getWindow(handle, GW_OWNER) is the same as the one returned by Application.Handle.Terrorist
@Craig's answer fleshes out my comments earlier in the day and are worth a go. That's where I was going with my question about the owner. Params.WndParent is how you set the owner.Congratulation
@David Heffernan: Using Application.Minimize and Application.Restore yields the same result as sending the messages.Terrorist
@Terrorist Try the window owner as described by Craig.Congratulation
@Sertac Akyuz: Thanks, it looks like you're right. It doesn't change the application's behavior, unfortunately.Terrorist
D
3

Override the dialog's CreateParams function and set Params.WndParent to the full-screen window (or Owner.Handle if you're owning things properly). The default is Application.Handle, which will cause these kinds of problems. The PopupParent properties introduced in the later Delphi releases does the exact same thing.

Decumbent answered 10/6, 2011 at 15:31 Comment(0)
D
1

This has to do with the Window ghosting by Windows which was introduced in (I think) XP. I have the same issues in a D5 app on these operating systems. Peter Below offered the following work around at the time and it still serves me well:

procedure DisableProcessWindowsGhosting;
type
  TDisableProcessWindowsGhostingProc = procedure; stdcall;
const
  sUser32 = 'User32.dll';
var
  ModH: HMODULE;
  _DisableProcessWindowsGhosting: TDisableProcessWindowsGhostingProc;
begin
  ModH := GetModuleHandle(sUser32);
  if ModH <> 0 then begin
    @_DisableProcessWindowsGhosting := nil;
    @_DisableProcessWindowsGhosting := GetProcAddress(ModH,
        'DisableProcessWindowsGhosting');
    if Assigned(_DisableProcessWindowsGhosting) then begin
      _DisableProcessWindowsGhosting;
    end;
  end;
end;

I call it at the beginning of the app's main form's OnCreate handler.

Drawers answered 10/6, 2011 at 11:32 Comment(6)
Not sure where you got ghosting from. And disabling ghosting is generally not ideal—keep pumping your queue!Congratulation
@David: generally not a good idea no. However, ghosts are created at various times. On non-responsiveness (which you are alluding to with pumping your queue I think) is just one of them. On minimizing the app window (you know the hidden one) was/is another. D5, D6 and possible D7 apps suffer from that and in this case just telling windows not to create a ghost window for this process seems ok to me as the alternative, a modal dialog hidden behind your main form, is far worse...Drawers
Thank you for the idea. I tried it and, unfortunately, it doesn't work :(Terrorist
@Stephane, sorry about that. Not sure I can help more though. This is a bit of "ancient history" for me too I'm afraid.Drawers
edit: Sorry, when I write "it doesn't work", I mean that it doesn't fix the problem of the modal form being under the maximized form when restoring the application from minimized state. The code executes correctly and completely.Terrorist
@Marjan: No problem, thank you for trying, I do appreciate it :)Terrorist

© 2022 - 2024 — McMap. All rights reserved.