Delphi 11 FMX如何在Windows及Mac平台检测窗口是否处于后台
Delphi 11 FMX 双平台窗口后台状态检测实现方案
以下实现兼容Windows、macOS双平台,适配多文档窗口场景:
核心检测方法封装
首先引入必要的单元引用:
- 通用单元:
FMX.Platform,System.SysUtils,FMX.Forms - Windows平台专属:
Winapi.Windows - macOS平台专属:
Macapi.AppKit,Macapi.Foundation
跨平台统一调用的检测函数如下:
function IsWindowInBackground(ATargetForm: TForm): Boolean; var LPlatformSrv: IFMXPlatformService; begin Result := False; // 优先判断目标窗口本身是否未激活 if not ATargetForm.Active then begin Result := True; Exit; end; // 结合平台原生API判断应用全局层级状态 if TPlatformServices.Current.SupportsPlatformService(IFMXPlatformService, LPlatformSrv) then begin {$IFDEF MSWINDOWS} // Windows逻辑:判断当前进程是否为前台进程 var LForegroundWnd := GetForegroundWindow; if LForegroundWnd <> 0 then begin var LProcessId: DWORD; GetWindowThreadProcessId(LForegroundWnd, @LProcessId); Result := LProcessId <> GetCurrentProcessId; end; {$ENDIF} {$IFDEF MACOS} // macOS逻辑:判断当前应用是否为活跃应用 var LSharedApp := TNSApplication.Wrap(TNSApplication.OCClass.sharedApplication); Result := not LSharedApp.isActive; {$ENDIF} end; end;
多文档窗口场景优化
如果需要单独判断单个文档窗口是否被其他窗口遮挡、处于后台层级,可补充以下平台特定逻辑:
- Windows下可调用
GetWindowPlacement判断窗口是否最小化,或通过GetNextWindow遍历Z轴层级确认窗口是否被遮挡 - macOS下可直接调用原生
NSWindow属性判断单个窗口状态:
{$IFDEF MACOS} function IsSingleMacWindowInBackground(ATargetForm: TForm): Boolean; var LTargetNSWindow: NSWindow; begin LTargetNSWindow := NSWindow(ATargetForm.Handle); // isKeyWindow判断是否为输入焦点窗口,isOccluded判断是否被其他窗口完全遮挡 Result := not LTargetNSWindow.isKeyWindow or LTargetNSWindow.isOccluded; end; {$ENDIF}
状态变更监听方案
不需要轮询检测的场景,可通过事件绑定实现实时状态更新:
- 绑定所有文档窗口的
OnActivate、OnDeactivate事件 - Windows下监听
WM_ACTIVATEAPP系统消息 - macOS下监听
NSApplicationDidBecomeActiveNotification、NSApplicationDidResignActiveNotification系统通知
注意:不要直接依赖FMX自带的
Application.Active属性做跨平台判断,该属性在macOS多窗口场景下存在偶发返回值偏差,优先以原生API获取的状态为准。
内容的提问来源于stack exchange,提问作者Mike at Bookup
相关产品推荐
相关产品推荐

