MFC如何监听其他应用程序的窗口大小变化?
Windows MFC 监听外部窗口Resize事件的实现方案
针对你需要监听外部应用窗口大小变化、避免轮询导致高CPU占用的需求,Windows平台可以使用WinEventHook机制实现类似MacOS中kAXWindowResizedNotification的效果,以下是具体实现步骤和代码示例:
核心思路
通过Windows原生API SetWinEventHook 注册钩子,监听EVENT_OBJECT_LOCATIONCHANGE事件——该事件会在窗口的位置或大小发生变化时触发。我们可以在回调中过滤出目标应用的窗口事件,仅在窗口resize时执行录屏尺寸更新逻辑。
具体实现代码
1. 声明全局/成员变量
用于保存钩子句柄和目标窗口句柄:
#include <windows.h> #include <winuser.h> HWINEVENTHOOK g_hWinEventHook = nullptr; HWND g_targetHWND = nullptr; // 要监听的目标应用窗口句柄
2. 查找目标窗口句柄(通过PID)
先根据目标应用的PID找到对应的主窗口句柄:
void FindTargetWindowByPID(DWORD targetPID) { EnumWindows([](HWND hwnd, LPARAM lParam) -> BOOL { DWORD pid; GetWindowThreadProcessId(hwnd, &pid); // 匹配PID且窗口可见,取第一个可见窗口作为目标 if (pid == (DWORD)lParam && IsWindowVisible(hwnd)) { g_targetHWND = hwnd; return FALSE; // 找到后停止枚举 } return TRUE; }, (LPARAM)targetPID); }
3. 注册窗口Resize监听钩子
void SetupResizeListener(DWORD targetPID) { FindTargetWindowByPID(targetPID); if (!g_targetHWND) return; // 注册WinEvent钩子,监听窗口位置/大小变化 g_hWinEventHook = SetWinEventHook( EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_LOCATIONCHANGE, nullptr, WinEventProc, targetPID, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS ); }
4. 钩子回调函数(处理Resize事件)
在回调中判断是否是目标窗口的resize事件,并执行相应逻辑:
void CALLBACK WinEventProc(HWINEVENTHOOK hook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime) { // 仅处理目标窗口的顶层窗口事件 if (hwnd != g_targetHWND || idObject != OBJID_WINDOW || idChild != CHILDID_SELF) return; // 窗口大小已变化,获取新尺寸并更新录屏参数 RECT windowRect; GetWindowRect(hwnd, &windowRect); int newWidth = windowRect.right - windowRect.left; int newHeight = windowRect.bottom - windowRect.top; // TODO: 在这里更新你的录屏捕获尺寸逻辑 }
5. 程序退出时清理钩子
void CleanupResizeListener() { if (g_hWinEventHook) { UnhookWinEvent(g_hWinEventHook); g_hWinEventHook = nullptr; g_targetHWND = nullptr; } }
关键说明
- 该机制是事件驱动的,仅在窗口实际resize时触发回调,完全替代轮询方案,大幅降低CPU占用。
WINEVENT_OUTOFCONTEXT参数确保钩子在你的进程空间运行,无需注入目标进程。- 如果需要监听多个窗口,可以扩展逻辑保存多个目标HWND,在回调中逐一匹配。
内容的提问来源于stack exchange,提问作者ssroreo
相关产品推荐
相关产品推荐

