活动窗口更改时收到通知
Posted
技术标签:
【中文标题】活动窗口更改时收到通知【英文标题】:Getting notification when active window changes 【发布时间】:2017-06-09 12:21:48 【问题描述】:我试图让我的程序在焦点更改时获取当前活动窗口标题。我有以下回调:
LRESULT CALLBACK windowChangeHook(int nCode, WPARAM wParam, LPARAM lParam)
if (wParam == HCBT_SETFOCUS || lParam == HCBT_SETFOCUS)
cout << GetActiveWindowTitle();
return(CallNextHookEx(NULL, nCode, wParam, lParam));
我正在尝试按如下方式挂钩 WH_CBT:
HHOOK hhkWindowChange = SetWindowsHookEx(WH_CBT, windowChangeHook, 0, 0);
也许我只是愚蠢,但它没有按预期工作,有人知道为什么吗?
编辑: 程序似乎根本没有检测到窗口更改,我尝试将代码更改为此无济于事:
LRESULT CALLBACK windowChangeHook(int nCode, WPARAM wParam, LPARAM lParam)
if (nCode == HCBT_ACTIVATE || nCode == HCBT_SETFOCUS)
cout << "TEST";
return(CallNextHookEx(NULL, nCode, wParam, lParam));
【问题讨论】:
"...但它没有按预期工作.." 什么不工作:钩子的设置;钩子被调用;没有检测到焦点变化?如果您想检测不属于您的应用程序的窗口,您是否需要在 DLL 中实现挂钩? 抱歉,Richard 应该更具体一些,它似乎没有检测到窗口变化。 当然不是。您正在猜测如何使用 API。那是行不通的。阅读documentation。 【参考方案1】:你没有检查来自SetWindowsHookEx
的返回值!
windowChangeHook
需要在一个 DLL 中,其 HMODULE
在 hMod
参数中。
HCBT_*
值在 nCode
参数中传递!
您也可以尝试改用SetWinEventHook
...
【讨论】:
【参考方案2】:您没有正确处理WH_CBT
回调。
根据CBTProc callback function 文档:
nCode [输入] 类型:整数
钩子程序用来确定如何处理消息的代码。如果
nCode
小于零,钩子程序必须将消息传递给CallNextHookEx
函数而不做进一步处理并且应该返回CallNextHookEx
返回的值。此参数可以是以下值之一。...
HCBT_SETFOCUS 9 一个窗口即将获得键盘焦点。
wParam [输入] 类型:WPARAM
取决于
nCode
参数。详情请参阅以下备注部分。
lParam [输入] 类型:LPARAM
取决于
nCode
参数。有关详细信息,请参阅以下备注部分。
下表描述了每个
HCBT_
挂钩代码的wParam
和lParam
参数。...
HCBT_SETFOCUS wParam:指定获得键盘焦点的窗口句柄。 lParam:指定失去键盘焦点的窗口句柄。
您正在寻找错误参数中的HCBT_SETFOCUS
值。您还在检索错误窗口的标题,因为输入焦点实际上还没有切换窗口。
您的回调应该看起来更像这样(假设您的回调是在 DLL 中实现的,这是检测全局事件所必需的,这也意味着您需要在 64 位系统上使用单独的 32 位和 64 位 DLL。这在 @ 987654322@文档):
LRESULT CALLBACK windowChangeHook(int nCode, WPARAM wParam, LPARAM lParam)
if (nCode == HCBT_SETFOCUS)
HWND hwnd = (HWND) wParam;
// retreive and use the title of hwnd as needed...
return CallNextHookEx(NULL, nCode, wParam, lParam);
话虽如此,您应该考虑改用SetWinEventHook()
,如果您使用“上下文外”钩子,则它没有DLL要求:
回调函数没有映射到产生事件的进程的地址空间。因为钩子函数是跨进程边界调用的,所以系统必须对事件进行排队。尽管此方法是异步的,但可以保证事件是按顺序排列的。如需更多信息,请参阅Out-of-Context Hook Functions。
EVENT_OBJECT_FOCUS 0x8005
对象已获得键盘焦点。系统为以下用户界面元素发送此事件:列表视图控件、菜单栏、弹出菜单、切换窗口、选项卡控件、树视图控件和窗口对象。服务器应用程序为其可访问对象发送此事件。
WinEventProc
回调函数的hwnd
参数标识接收键盘焦点的窗口。
例如:
void CALLBACK windowChangeHook(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
// retreive and use the title of hwnd as needed...
HWINEVENTHOOK hEventHook = SetWinEventHook(EVENT_OBJECT_FOCUS, EVENT_OBJECT_FOCUS, NULL, &windowChangeHook, 0, 0, WINEVENT_OUTOFCONTEXT);
...
UnhookWinEvent(hEventHook);
【讨论】:
以上是关于活动窗口更改时收到通知的主要内容,如果未能解决你的问题,请参考以下文章