在活动窗口更改时获取通知

时间:2017-06-09 12:21:48

标签: c++ windows winapi hook

我正在尝试让我的程序在焦点更改时获取当前活动窗口标题。我有以下CALLBACK:

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));
}

2 个答案:

答案 0 :(得分:3)

  • 您没有检查SetWindowsHookEx的返回值!

  • windowChangeHook需要位于HMODULE参数中hMod的DLL中。

  • HCBT_*参数传递nCode值!

您也可以尝试使用SetWinEventHook代替...

答案 1 :(得分:0)

您没有正确处理WH_CBT回调。

根据CBTProc callback function文档:

  

nCode [in]
  键入:int

     

钩子过程用于确定如何处理消息的代码。如果nCode小于零,则钩子过程必须将消息传递给CallNextHookEx函数没有进一步处理,应返回CallNextHookEx返回的值。此参数可以是以下值之一。

     

...

     

HCBT_SETFOCUS
  9
  窗口即将接收键盘焦点。

  

wParam [in]
  键入:WPARAM

     

取决于nCode参数。有关详细信息,请参阅以下备注部分。

  

lParam [in]
  键入:LPARAM

     

取决于nCode参数。有关详细信息,请参阅以下备注部分。

  

下表介绍了每个wParam挂钩代码的lParamHCBT_参数。

     

...

     

HCBT_SETFOCUS
  wParam:指定获得键盘焦点的窗口的句柄   lParam:指定失去键盘焦点的窗口的句柄。

您正在寻找错误参数中的HCBT_SETFOCUS值。您还在检索错误窗口的标题,因为输入焦点尚未实际切换窗口。

你的回调应该看起来更像这样(假设你的回调是在DLL中实现的,这是检测全局事件所必需的,这也意味着你需要在64位系统上使用单独的32位和64位DLL。这在{ {3}}文档):

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);
}

话虽如此,你应该考虑使用SetWindowsHookEx()代替,如果你使用钩子“out-of-context”,它没有DLL要求:

  

回调函数未映射到生成事件的进程的地址空间。由于跨函数边界调用钩子函数,因此系统必须对事件进行排队。虽然此方法是异步的,但事件保证按顺序排列。有关详细信息,请参阅SetWinEventHook()

  

EVENT_OBJECT_FOCUS
  0x8005

     

对象已获得键盘焦点。系统为以下用户界面元素发送此事件:列表视图控件,菜单栏,弹出菜单,切换窗口,选项卡控件,树视图控件和窗口对象。服务器应用程序为其可访问对象发送此事件。

     

hwnd回调函数的WinEventProc参数标识了获得键盘焦点的窗口

例如:

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);