【发布时间】:2019-04-08 10:37:19
【问题描述】:
我正在尝试从我的班级挂钩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。所以问题是为什么我的钩子不起作用?
谢谢。
【问题讨论】:
-
尝试在
SetWindowsHookEx调用上设置threadId -
另外,钩子程序似乎总是会转发到为其设置的最后一个窗口.. (m_pThis) - 这是故意的吗?
-
使用
m_pThis是因为我不能使用非静态函数作为SetWindowsHookEx参数,所以我使用带有静态指针的静态函数。从SetWindowsHookEx文档中可以看出,该函数应该在 ThreadId = 0 的情况下工作,但我会尝试通过调用GetCurrentThreadId来设置 ThreadId -
使用
GetCurrentThreadId没有帮助 -
@rudolfninja "我不能将非静态函数用作
SetWindowsHookEx参数" - 如果您使用 thunk 进行回调,则可以。但这是大多数编码人员不知道如何使用的高级技术。 “该函数应该与 ThreadId = 0 一起使用” - 这需要钩子代码驻留在一个 DLL 中,然后注入到其他进程中,因为钩子回调在每个检索线程的上下文中运行窗口消息。这意味着您需要单独的 DLL 来挂钩 32 位和 64 位进程。