Browse Source

Improve OnGetActiveFormHandle handler.

Use GetLastActivePopup instead of Screen.ActiveForm.
- Screen.ActiveForm doesn't support non-VCL windows like the IDE's Find dialog.
- Screen.ActiveForm can be nil if the main form has been shown but never became the active window.
- Screen.ActiveForm can be nil if the active form was destroyed and another form hasn't been activated yet.

Jordan Russell 8 months ago
parent
commit
4b9b9576aa
2 changed files with 25 additions and 14 deletions
  1. 18 10
      Projects/Src/IDE.MainForm.pas
  2. 7 4
      Projects/Src/Setup.MainForm.pas

+ 18 - 10
Projects/Src/IDE.MainForm.pas

@@ -1196,16 +1196,24 @@ begin
     there are no popups owned by the application window).
     So if the application calls Application.MessageBox while it isn't in the
     foreground, that message box will be owned by Application.Handle, not by
-    the last-active form as it should be. That can lead to the message box
-    falling behind the form in z-order.
-    To rectify that, we return Screen.ActiveForm.Handle if possible, which is
-    valid whether or not the application is in the foreground. This code is
-    from TCustomTaskDialog.Execute. (HandleAllocated call added to be safe) }
-
-  if Assigned(Screen.ActiveForm) and
-     (Screen.ActiveForm.FormStyle <> fsMDIChild) and
-     Screen.ActiveForm.HandleAllocated then
-    AHandle := Screen.ActiveForm.Handle;
+    the last-active window as it should be. That can lead to the message box
+    falling behind the main form in z-order.
+    To rectify that, when no window is active and MainFormOnTaskBar=True, we
+    fall back to returning the handle of the main form's last active popup,
+    which is the window that would be activated if the main form's taskbar
+    button were clicked. (If Application.Handle is active, we treat that the
+    same as no active window because Application.Handle shouldn't be the owner
+    of any windows when MainFormOnTaskBar=True.)
+    If there is no assigned main form or if MainFormOnTaskBar=False, then we
+    fall back to the default handling. }
+
+  if Application.MainFormOnTaskBar then begin
+    AHandle := GetActiveWindow;
+    if ((AHandle = 0) or (AHandle = Application.Handle)) and
+       Assigned(Application.MainForm) and
+       Application.MainForm.HandleAllocated then
+      AHandle := GetLastActivePopup(Application.MainFormHandle);
+  end;
 end;
 
 procedure TMainForm.FormAfterMonitorDpiChanged(Sender: TObject; OldDPI,

+ 7 - 4
Projects/Src/Setup.MainForm.pas

@@ -506,10 +506,13 @@ end;
 class procedure TMainForm.AppOnGetActiveFormHandle(var AHandle: HWND);
 begin
   { IDE's TMainForm has this too; see comments there }
-  if Assigned(Screen.ActiveForm) and
-     (Screen.ActiveForm.FormStyle <> fsMDIChild) and
-     Screen.ActiveForm.HandleAllocated then
-    AHandle := Screen.ActiveForm.Handle;
+  if Application.MainFormOnTaskBar then begin
+    AHandle := GetActiveWindow;
+    if ((AHandle = 0) or (AHandle = Application.Handle)) and
+       Assigned(Application.MainForm) and
+       Application.MainForm.HandleAllocated then
+      AHandle := GetLastActivePopup(Application.MainFormHandle);
+  end;
 end;
 
 initialization