【问题标题】:Confusion about mouse hooks in c++关于 C++ 中鼠标钩子的困惑
【发布时间】:2013-04-12 10:05:33
【问题描述】:

我正在尝试获取全局鼠标位置。我有一个可以获取鼠标位置的钩子,但是它只能在钩子代码中访问它。尝试访问 main 中的数据不起作用。

解释这一点的最好方法是用代码:

LRESULT CALLBACK mouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
     PMSLLHOOKSTRUCT p = (PMSLLHOOKSTRUCT) lParam;
     position.x = p->pt.x;
     position.y = p->pt.y;
     std::cout<<position.x<<std::endl;
     return CallNextHookEx(NULL, nCode, wParam, lParam);
}

int WINAPI WinMain (HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszArgument,int nCmdShow)
{
     HHOOK mouseHook = SetWindowsHookEx(WH_MOUSE_LL,mouseHookProc,hInstance,NULL);

     MessageBox(NULL, "Press OK to close.", "", MB_OK);
     return 0;
}

使用上面的代码,移动鼠标将在控制台窗口中显示新的位置。但是,如果我把 std::cout&lt;&lt;position.x&lt;&lt;std::endl; 放在 main 里面,它只会说 0。position 是一个全局变量。

输出在 main 内部时的代码:

LRESULT CALLBACK mouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
     PMSLLHOOKSTRUCT p = (PMSLLHOOKSTRUCT) lParam;
     position.x = p->pt.x;
     position.y = p->pt.y;

     return CallNextHookEx(NULL, nCode, wParam, lParam);
}

int WINAPI WinMain (HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszArgument,int nCmdShow)
{
     HHOOK mouseHook = SetWindowsHookEx(WH_MOUSE_LL,mouseHookProc,hInstance,NULL);
     for(;;)
     {
         std::cout<<position.x<<std::endl;
     }
     MessageBox(NULL, "Press OK to close.", "", MB_OK);
     return 0;
}

第一段代码工作正常,它检测鼠标位置,我只是不知道如何将 x,y 数据放入我的 main 中。

【问题讨论】:

  • 最新的C++2011标准不了解鼠标。您肯定是在谈论一些特定于系统的 API(可能是 Windows)。
  • 我认为如果 mouseHookProc 在 dll 中,全局鼠标钩子可以工作
  • 显示代码,其输出位于main
  • 你把代码放在哪里? MessageBox 有自己的消息泵,在它被关闭之前不会返回。

标签: c++ windows hook mousemove mouse-hook


【解决方案1】:

这是发布的代码:

LRESULT CALLBACK mouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
     PMSLLHOOKSTRUCT p = (PMSLLHOOKSTRUCT) lParam;
     position.x = p->pt.x;
     position.y = p->pt.y;

     return CallNextHookEx(NULL, nCode, wParam, lParam);
}

int WINAPI WinMain (HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszArgument,int nCmdShow)
{
     HHOOK mouseHook = SetWindowsHookEx(WH_MOUSE_LL,mouseHookProc,hInstance,NULL);
     std::cout<<position.x<<std::endl;
     MessageBox(NULL, "Press OK to close.", "", MB_OK);
     return 0;
}

这是主函数指定的应该发生的事情:

  • 首先,调用SetWindowsHookEx(只发生一次)。
  • 然后,输出position(这种情况发生一次)。
  • 然后,显示MessageBox(这种情况发生一次)。

就是这样。

在调用MessageBox 期间,会调用挂钩过程(每当您移动鼠标时),但它不会做任何可见的事情,只是进行内部更新。

你为什么期待更多?


如何解决:

  • 不要依赖 MessageBox 中的内部消息循环,它不会进行任何输出,而是自己编写代码。
  • 与功能无关,只是因为当前的代码就像非常脏的衣服,确实可以达到目的,但穿起来不好看:用标准的 C 和 C++ main 替换 Microsoft 的 WinMain 怪物。

【讨论】:

  • 我不小心把第二部分的代码贴错了,有一个无限循环试图输出位置。我想既然钩子正在运行,它会不断更新位置。但事实并非如此。
  • 更多混乱...如果我将 cout / msgbox 更改为多个(msgbox,cout,msgbox,cout ....msgbox,cout)然后按 ok 将显示位置,下一个ok 将显示位置,依此类推。但是,当在无限循环中打印时,我的鼠标非常迟钝,我得到的只是 0
  • 一个消息循环反复调用GetMessage。对于每条消息,您通常会调用 TranslateMessageDispatchMessage
  • “用标准的 C 和 C++ main 替换 Microsoft 的 WinMain 怪物。”那怎么生产?在 Visual Studio 中,这只是自找麻烦,除非您也想摆弄链接器设置和项目设置。适合您的目标平台并遵循平台持有者的建议有什么问题?我什至会称其为最佳实践......
  • @jheriko:我理解你的情绪反应,我很同情。不过请放心,随着您使用这些工具获得更多经验,您也会对自己的判断更有信心,而对微软的信心会降低。现在看起来不可能不符合你的东西,比如哦,我们不能摆弄设置!,哦不!,然后才会看起来合理;那些现在看起来很完美的方式和设置,就像它们一样来自微软,即使只是一眼,也会显示出严重的缺点和问题。你还不在那里。坚持住,你会到达那里的。
【解决方案2】:

对于全局挂钩,挂钩过程mouseHookProc 应位于DLL 中,以便可以将其注入进程。 检查这个: http://www.codeproject.com/Articles/1037/Hooks-and-DLLs

【讨论】:

  • 如何从 dll 中获取鼠标位置?我以前没有使用过编码 dll。
  • 从 dll 中,您可以使用 PostMessage 使用主应用程序窗口的句柄将详细信息发布到主应用程序。使用自定义消息,应用程序应为此注册。鼠标详细信息可以传递为wparamlparamPostMessage。还有几种方法可以使用 API 来处理窗口。另一种方法是在加载 dll 时传递句柄。
猜你喜欢
  • 2020-09-22
  • 1970-01-01
  • 2013-07-23
  • 1970-01-01
  • 2012-03-26
  • 2014-11-29
  • 2014-04-11
  • 1970-01-01
  • 2019-05-17
相关资源
最近更新 更多