提问人:vibhav950 提问时间:10/14/2023 最后编辑:vibhav950 更新时间:10/20/2023 访问量:179
SetWindowsHookExW 不调用 MouseProc 回调过程
SetWindowsHookExW not calling the MouseProc callback procedure
问:
因此,我正在尝试用 C 语言运行一个简单的代码,该代码在每次移动时打印鼠标的位置。为了让程序运行一段时间然后退出,我使用了如下所示的 for 循环。我希望钩子仅与当前线程相关联。 代码如下:
#include <stdio.h>
#include <windows.h>
// Global hook handle
HHOOK hHook = NULL;
// Mouse hook callback
LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) {
printf("Entered\n");
if (nCode >= 0) {
if ((nCode == HC_ACTION) && (wParam == WM_MOUSEMOVE)) {
MOUSEHOOKSTRUCT* pMouseStruct = (MOUSEHOOKSTRUCT*)lParam;
printf("Mouse X: %ld, Mouse Y: %ld\n", pMouseStruct->pt.x, pMouseStruct->pt.y);
}
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
int main() {
// Install the mouse hook
hHook = SetWindowsHookEx(WH_MOUSE, (HOOKPROC) &MouseHookProc, NULL, GetCurrentThreadId());
if (hHook == NULL) {
printf("Hook installation failed\n");
return 1;
}
// Keep program running (edit 1)
MSG msg;
while (GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Unhook and exit
UnhookWindowsHookEx(hHook);
return 0;
}
printf 语句永远不会被执行。为什么即使成功设置了钩子,进程也没有被调用?
编辑:我很抱歉没有明确提及这一点,但我最初尝试使用消息循环而不是上面显示的循环,但结果是一样的。但是,如果我改用低级鼠标钩子,它确实有效。为什么会这样?for
WH_MOUSE_LL
更新:我会试着描述我想要实现的更好目标。首先,我正在尝试制作一个独立的控制台可执行文件,而不是 Windows 应用程序。我最初尝试轮询鼠标位置的次数有限,但现在我相信对于我的应用程序来说,更好的方法是只要程序处于活动状态,就进行采样,然后释放钩子以及其他清理作业以优雅地退出程序。我面临的问题是我无法使用普通的鼠标钩而不是低级的鼠标钩。我从一些来源读到,钩子过程必须通过DLL注入到可执行文件中,但我也无法让它工作。现在唯一有效的是一个低级鼠标钩子,它减慢了我的程序速度并使其几乎无法使用。WM_MOUSE
WM_MOUSE_LL
答:
正如注释中指出的,您需要一个 Win32 消息循环才能接收挂钩事件。WH_MOUSE
https://learn.microsoft.com/en-us/windows/win32/winmsg/mouseproc
可以在安装它的线程的上下文中调用此钩子。通过向安装挂钩的线程发送消息来进行调用。因此,安装钩子的线程必须具有消息循环。
示例 (main.cpp):
#include <Windows.h>
#include <iostream>
static HHOOK p_hook = nullptr;
BOOL WINAPI HandlerRoutine(_In_ DWORD dwCtrlType);
LRESULT CALLBACK LowLevelMouseProc(_In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM lParam);
int main()
{
if (SetConsoleCtrlHandler(HandlerRoutine, TRUE) == 0)
return ~0;
p_hook = SetWindowsHookEx(WH_MOUSE_LL, LowLevelMouseProc, nullptr, 0);
if (p_hook == nullptr)
return ~0;
MSG msg = { 0 };
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (p_hook != nullptr)
UnhookWindowsHookEx(p_hook);
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK LowLevelMouseProc(_In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM lParam)
{
if (nCode == HC_ACTION)
{
auto m_struct = reinterpret_cast<MSLLHOOKSTRUCT*>(lParam);
std::cout << "x: " << m_struct->pt.x << " y: " << m_struct->pt.y << std::endl;
}
return CallNextHookEx(p_hook, nCode, wParam, lParam);
}
BOOL WINAPI HandlerRoutine(_In_ DWORD dwCtrlType)
{
if (dwCtrlType == CTRL_CLOSE_EVENT || dwCtrlType == CTRL_SHUTDOWN_EVENT)
{
if (UnhookWindowsHookEx(p_hook) == TRUE)
p_hook = nullptr;
}
return TRUE;
}
评论
WH_MOUSE
WH_MOUSE_LL
正如我在评论中所说,绝对可以正常工作。WH_MOUSE
使用“监视系统事件”文档示例。
我需要停止轮询并释放钩子一次(比如说 100)的不同位置已被记录下来。
评论
/SUBSYSTEM:CONSOLE
/SUBSYSTEM:WINDOWS
上一个:获取区域设置信息常量的默认值
下一个:在 C 语言中实现矩阵加法
评论
WH_MOUSE_LL