Proper handling of modal window “Minimize” behavio

2019-04-07 22:39发布

问题:

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.

回答1:

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.



回答2:

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.