Крюк WH_GETMESSAGE сообщение
Я пытаюсь подключить 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. Итак, вопрос в том, почему мой крючок не работает? Благодарю.
m_msgHook = SetWindowsHookEx(WH_GETMESSAGE, MsgPoc, NULL, 0);
Эта строка выдает системную ошибку ERROR_HOOK_NEEDS_HMOD (1428). Это означает, что невозможно установить нелокальный хук без дескриптора модуля. Если вы установите параметр dwThreadId
в ноль, процедура подключения будет связана со всеми существующими потоками, работающими на том же рабочем столе, что и вызывающий поток. Это не загружаемый хук, вам нужно указать правильный параметр hmod
. Вам нужно поместить код подключения в DLL, как указывал @Remy Lebeau.
Или установите действительный параметр dwThreadId
используя GetCurrentThreadId(), как указано @rudolfninja.
Я тестирую на основе шаблона приложения для рабочего стола 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);
}