挂钩WH_GETMESSAGE消息

时间:2019-04-08 10:37:19

标签: c++ winapi hook

我正试图将WH_GETMESSAGE与我的班级联系起来,以确定何时调整特定窗口的大小。但是,好像没有设置钩子。

我尝试钩住的类:

class WindowDisplayHelper : // public ...
{    
public:
    // some other public methods here
    void SetMsgHook();
protected:
    LRESULT CALLBACK GetMsgProcHook(int code, WPARAM wParam, LPARAM lParam);
    static LRESULT CALLBACK MsgPoc(int code, WPARAM wParam, LPARAM lParam);
private:
    // some other private members there
    HWND m_windowHandle;
    bool m_isWindowResizing = false;
    static HHOOK m_msgHook;
    static WindowsDisplayHelperMasterWindow* m_pThis;
};

.cpp文件:

WindowDisplayHelper* WindowDisplayHelper ::m_pThis = nullptr;
HHOOK WindowDisplayHelper ::m_msgHook = NULL;

void WindowDisplayHelper ::SetMsgHook()
{
    m_pThis = this;
    m_msgHook = SetWindowsHookEx(WH_GETMESSAGE, MsgPoc, NULL, 0);
}

LRESULT CALLBACK WindowDisplayHelper::MsgPoc(int code, WPARAM wParam, LPARAM lParam)
{
    if (m_pThis != nullptr)
    {
        return m_pThis->GetMsgProcHook(code, wParam, lParam);
    }
    return CallNextHookEx(0, code, wParam, lParam);
}

LRESULT CALLBACK WindowDisplayHelper::GetMsgProcHook(int code, WPARAM wParam, LPARAM lParam)
{
    DUMPER_INFO("Hooked");
    if (code < 0)
    {
        return CallNextHookEx(0, code, wParam, lParam);
    }
    MSG* lpmsg = (MSG*)lParam;
    DUMPER_INFO("Hooked for HWND: %p. Current window %p", lpmsg->hwnd, m_windowHandle);
    if (lpmsg->hwnd != m_windowHandle)
    {
        return CallNextHookEx(0, code, wParam, lParam);
    }
    if (lpmsg->message == WM_ENTERSIZEMOVE && !m_isWindowResizing)
    {
        DUMPER_INFO("Start window resizing");
        m_isWindowResizing = true;
    }
    else if (lpmsg->message == WM_EXITSIZEMOVE && m_isWindowResizing)
    {
        DUMPER_INFO("Stop window resizing");
        m_isWindowResizing = false;
    }

    return CallNextHookEx(0, code, wParam, lParam);
}

这是我创建WindowDisplayHelper对象的方式:

bool DisplayManager::CreateWindowDisplay(TDisplayId displayId, void * windowHandle)
{
    auto helper = boost::make_shared<WindowDisplayHelper>(windowHandle);
    helper->SetMsgHook();
    AddDisplayHelper(displayId, helper);

    return true;
}

尽管在创建对象后调用SetMsgHook(),但好像未设置钩子,因为在日志文件中我看不到任何调试输出,并且m_isWindowResizing变量始终== false。所以问题是为什么我的钩子不起作用? 谢谢。

1 个答案:

答案 0 :(得分:0)

m_msgHook = SetWindowsHookEx(WH_GETMESSAGE, MsgPoc, NULL, 0);

此行产生ERROR_HOOK_NEEDS_HMOD(1428)system error。这意味着没有模块句柄就无法设置非本地钩子。如果将dwThreadId参数设置为零,则挂钩过程将与在与调用线程相同的桌面中运行的所有现有线程关联。这是一个非负载挂钩,您需要指定一个有效的hmod参数。您需要按照@Remy Lebeau指出的那样,将挂钩代码放入DLL中。

或如@rudolfninja所指出的那样,使用GetCurrentThreadId()设置有效的dwThreadId参数。

我基于Windows桌面应用模板使用以下代码进行测试。有用。您可以尝试一下。

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    // ...

    HHOOK m_msgHook = SetWindowsHookEx(WH_GETMESSAGE, MsgPoc, NULL, GetCurrentThreadId());
    DWORD errCode = GetLastError();

    MSG msg;

    // Main message loop:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}

LRESULT CALLBACK MsgPoc(int code, WPARAM wParam, LPARAM lParam)
{
    OutputDebugString(L"Hooked");
    if (code < 0)
    {
        return CallNextHookEx(0, code, wParam, lParam);
    }
    MSG* lpmsg = (MSG*)lParam;
    //OutputDebugString("Hooked for HWND: %p. Current window %p", lpmsg->hwnd, m_windowHandle);
    if (lpmsg->hwnd != m_windowHandle)
    {
        return CallNextHookEx(0, code, wParam, lParam);
    }
    if (lpmsg->message == WM_ENTERSIZEMOVE && !m_isWindowResizing)
    {
        OutputDebugString(L"Start window resizing");
        m_isWindowResizing = true;
    }
    else if (lpmsg->message == WM_EXITSIZEMOVE && m_isWindowResizing)
    {
        OutputDebugString(L"Stop window resizing");
        m_isWindowResizing = false;
    }

    return CallNextHookEx(0, code, wParam, lParam);
}