在活动 window 发生变化时收到通知

Getting notification when active window changes

我试图让我的程序在焦点改变时获取当前活动的 window 标题。我有以下回调:

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

也许我只是太笨了,但它没有按预期工作,有人知道为什么吗?

编辑: 程序似乎根本没有检测到 window 更改,我尝试将代码更改为此无济于事:

LRESULT CALLBACK windowChangeHook(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode == HCBT_ACTIVATE || nCode == HCBT_SETFOCUS)
        cout << "TEST";

    return(CallNextHookEx(NULL, nCode, wParam, lParam));
}
  • 您没有检查 SetWindowsHookEx 中的 return 值!

  • windowChangeHook 需要在 DLL 中,其 HMODULEhMod 参数中。

  • nCode参数中传递了HCBT_*值!

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

您没有正确处理 WH_CBT 回调。

根据 CBTProc callback function 文档:

nCode [in]
Type: int

The code that the hook procedure uses to determine how to process the message. If nCode is less than zero, the hook procedure must pass the message to the CallNextHookEx function without further processing and should return the value returned by CallNextHookEx. This parameter can be one of the following values.

...

HCBT_SETFOCUS
9
A window is about to receive the keyboard focus.

wParam [in]
Type: WPARAM

Depends on the nCode parameter. For details, see the following Remarks section.

lParam [in]
Type: LPARAM

Depends on the nCode parameter. For details, see the following Remarks section.

The following table describes the wParam and lParam parameters for each HCBT_ hook code.

...

HCBT_SETFOCUS
wParam: Specifies the handle to the window gaining the keyboard focus.
lParam: Specifies the handle to the window losing the keyboard focus.

您在错误的参数中查找 HCBT_SETFOCUS 值。您还检索了错误的标题 window,因为输入焦点尚未实际切换 windows。

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

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(),如果您使用挂钩 "out-of-context":

,它就没有 DLL 要求

The callback function is not mapped into the address space of the process that generates the event. Because the hook function is called across process boundaries, the system must queue events. Although this method is asynchronous, events are guaranteed to be in sequential order. For more information, see Out-of-Context Hook Functions.

EVENT_OBJECT_FOCUS
0x8005

An object has received the keyboard focus. The system sends this event for the following user interface elements: list-view control, menu bar, pop-up menu, switch window, tab control, tree view control, and window object. Server applications send this event for their accessible objects.

The hwnd parameter of the WinEventProc callback function identifies the window that receives the keyboard focus.

例如:

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