fix(hotkeys): find the native dialog by enumerating the thread windows
GetLastActivePopup returns the form itself - the common Save dialog is not an owned popup - so the code that raises it never ran. It does live on our thread with the standard #32770 class, which EnumThreadWindows finds regardless of its owner. Logging confirmed two things worth keeping: WM_HOTKEY is dispatched during the dialog modal loop, and IsWindowEnabled detects the state correctly.
This commit is contained in:
@@ -201,6 +201,11 @@ implementation
|
||||
|
||||
{$R *.fmx}
|
||||
|
||||
// Result slot for EnumOwnDialogProc — the enumeration is main-thread only and
|
||||
// consumed immediately, so a unit variable is enough.
|
||||
var
|
||||
GFoundDialogHwnd: HWND = 0;
|
||||
|
||||
// Forward — used by WebBrowserInitialized (which sits above the actual
|
||||
// definition lower in the unit).
|
||||
function MaskAccessToken(const AUrl: string): string; forward;
|
||||
@@ -503,6 +508,24 @@ end;
|
||||
// the user can no longer find. Every hotkey entry point checks this first — and
|
||||
// rather than just refusing, it surfaces the dialog, which is what the user
|
||||
// actually needs.
|
||||
// The common Save/Open dialog is NOT an owned popup of the form —
|
||||
// GetLastActivePopup returns the form itself — but it does live on our thread
|
||||
// and carries the standard dialog class. Enumerating the thread's windows finds
|
||||
// it whoever its owner turns out to be.
|
||||
function EnumOwnDialogProc(AWnd: HWND; AParam: LPARAM): BOOL; stdcall;
|
||||
var
|
||||
LCls: array[0..63] of Char;
|
||||
begin
|
||||
Result := True; // keep enumerating
|
||||
if (AWnd = HWND(AParam)) or (not IsWindowVisible(AWnd)) then Exit;
|
||||
if GetClassName(AWnd, LCls, Length(LCls)) = 0 then Exit;
|
||||
if SameText(LCls, '#32770') then
|
||||
begin
|
||||
GFoundDialogHwnd := AWnd;
|
||||
Result := False; // stop
|
||||
end;
|
||||
end;
|
||||
|
||||
function TMainForm.NativeModalActive: Boolean;
|
||||
var
|
||||
LHwnd, LPopup: HWND;
|
||||
@@ -510,7 +533,10 @@ begin
|
||||
LHwnd := WindowHandleToPlatform(Self.Handle).Wnd;
|
||||
Result := (LHwnd <> 0) and (not IsWindowEnabled(LHwnd));
|
||||
if not Result then Exit;
|
||||
LPopup := GetLastActivePopup(LHwnd);
|
||||
GFoundDialogHwnd := 0;
|
||||
EnumThreadWindows(GetCurrentThreadId, @EnumOwnDialogProc, LPARAM(LHwnd));
|
||||
LPopup := GFoundDialogHwnd;
|
||||
if LPopup = 0 then LPopup := GetLastActivePopup(LHwnd); // fallback
|
||||
if (LPopup <> 0) and (LPopup <> LHwnd) and IsWindow(LPopup) then
|
||||
begin
|
||||
ShowWindow(LPopup, SW_SHOW);
|
||||
|
||||
Reference in New Issue
Block a user