Reputation: 274
The scenario is that I have a 'main app' and a 'helper app'. The 'helper app' pops up on a keyboard hook, does it's stuff, then refocuses the main app window. The problem is that if the main app pops up a modal dialog when helper is active, and the helper then refocuses the wrong window, the modal dialog is hidden and the main app appears 'frozen'.
Any suggestions of strategies to solve this?
Upvotes: 4
Views: 1059
Reputation: 54832
It looks like the modal form of the 'main app' is not owned by the main app window, otherwise the modal form would stay above the main form at all times. So, possibly, either there's no MainFormOnTaskbar
property for the Delphi version that it was compiled, or it is not set. Then it must be the hidden application window that owns the windows.
You can test if the main app window is disabled when closing your 'helper app' form (that would be the case if there's a modal form), and restore the last active popup window that is owned by the hidden application window if it is.
var
Wnd: HWND; // handle to 'main app's main form
mWnd: HWND; // handle to possible modal form
AppWnd: HWND; // handle to hidden Application window
begin
..
if not IsWindowEnabled(Wnd) then begin // test if there's a modal form
AppWnd := GetWindowLong(Wnd, GWL_HWNDPARENT); // TApplication window handle
mWnd := GetLastActivePopup(AppWnd); // most recently active popup window
// restore focus to mWnd
end else
// restore focus to Wnd
(Don't forget to include tests for the result of the API functions of course.)
Upvotes: 1
Reputation: 43664
Try Application.Restore
or Application.RestoreTopMosts
. And when that modal dialog is shown by a WinAPI call, then also try Application.Normalize(All)TopMosts
before.
Now, this could be sufficient, but in my own application which hides the application handle from the taskbar, it doesn't and I needed the following routine which is the handler of a TApplicationEvents.OnActivate
event:
procedure TMainForm.AppEventsActivate(Sender: TObject);
var
TopWindow: HWND;
begin
TopWindow := GetLastActivePopup(Application.Handle);
if (TopWindow <> 0) and (TopWindow <> Application.Handle) then
begin
BringToFront;
SetForegroundWindow(TopWindow);
end;
end;
Clarification: the code in Application.BringToFront
is almost the same, but it does not guarantee to also show the main form in the background. I.e. Application.BringToFront
may show only the modal dialog.
Upvotes: 0