MouseProc 挂钩和 WM_LBUTTONDBLCLK
我有一个钩子设置,用于在我开发的插件中获取鼠标事件。我需要获取 WM_LBUTTONDBLCLK,并且我希望消息流为:
WM_LBUTTONDOWN、WM_LBUTTONUP、WM_LBUTTONDBLCLK
如果我在处理第一个 WM_LBUTTONDOWN 时调用下一个挂钩,那么流程就如预期的那样。但是,如果我返回自己的结果,则预期的双击将作为鼠标按下消息出现。知道为什么会发生这种情况吗?我需要消息在处理后停止,而不是将其传递到下一个钩子。
I have a hook setup for getting mouse events in a plugin I develop. I need to get the WM_LBUTTONDBLCLK
, and I expect the message flow to be:
WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBLCLK
If I call the next hook when dealing with the first WM_LBUTTONDOWN
, then the flow is as expected. However, if I return my own result, then the expected double click comes as a mouse down message. Any idea why this is happening? I need the message to stop after I handle it, and not have it passed to the next hook.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在 MSDN 上阅读了一些内容后,我认为这种行为的解释在于
WM_LBUTTONDBLCLK
页面:如果您的程序在处理
WM_LBUTTONDOWN
或WM_LBUTTONUP
时返回非零值,则这些消息不会按预期发送到目标窗口。然而,根据上面的引用,我的推断是,由于没有具有CS_DBLCLKS
样式的窗口因此接收消息(因为钩子阻止任何窗口接收消息),因此系统认为不需要生成WM_LBUTTONDBLCLK
。换句话说,系统仅生成一个
WM_LBUTTONDBLCLK
当且仅当 (a) 一个窗口接收到前一个WM_LBUTTONDOWN
/WM_LBUTTONUP
消息,并且 (b) 该窗口具有CS_DBLCLKS
样式。由于您的挂钩阻止满足条件 (a),因此永远不会生成WM_LBUTTONDBLCLK
,因此会发送WM_LBUTTONDOWN
消息。至于解决方法,我怀疑是否有完美的解决方案。我假设您想要接收
WM_LBUTTONDBLCLK
消息的原因是让您的钩子知道常规WM_LBUTTONDOWN
消息是否代表双击的第二次单击,对吗?在这种情况下,您可以按照 Faisal 的建议从注册表中读取双击时间,并让您的钩子测量WM_LBUTTONDOWN
消息之间的时间,但是您很可能会得到不准确的结果(由于发送消息之间存在延迟时间)。或者,如果有某种方法可以将WM_LBUTTONDOWN
/WM_LBUTTONUP
消息重定向到您的钩子拥有的隐藏窗口(其具有CS_DBLCLKS
样式) ),系统最终可能会生成一个WM_LBUTTONDBLCLK
消息并将其发送到您的隐藏窗口,然后您可以在该窗口的WndProc
中处理该消息(尽管我没有有很多挂钩经验,所以我不知道这是否可能)。After having done a little reading over at the MSDN, I think the explanation of this behaviour lies in this remark on the
WM_LBUTTONDBLCLK
page:If your program is returning a nonzero value when it handles
WM_LBUTTONDOWN
orWM_LBUTTONUP
, then those messages aren't sent to the target window -- as expected. However, my inference, based on the above quote, is that since no window with theCS_DBLCLKS
style is therefore receiving the messages (since the hook prevents any window from receiving the messages), the system therefore doesn't feel like it needs to generate aWM_LBUTTONDBLCLK
.To put it another way, the system only generates a
WM_LBUTTONDBLCLK
if and only if (a) a window receives the previousWM_LBUTTONDOWN
/WM_LBUTTONUP
messages and (b) that window has theCS_DBLCLKS
style. Since your hook prevents condition (a) from being satisfied,WM_LBUTTONDBLCLK
is never generated and so aWM_LBUTTONDOWN
message is sent instead.As to a workaround, I doubt there's a perfect solution. I assume the reason why you want to receive the
WM_LBUTTONDBLCLK
message is so your hook knows whether or not a regularWM_LBUTTONDOWN
message represents the second click of a double-click, right? In that case, what you could do is read the double-click time from the registry as Faisal suggests and have your hook measure the time betweenWM_LBUTTONDOWN
messages, however there's a large chance that you will get inaccurate results (due to the lag time between the messages being sent). Alternatively if there's some way you could instead redirect theWM_LBUTTONDOWN
/WM_LBUTTONUP
messages to maybe a hidden window that your hook owns (which has theCS_DBLCLKS
style), the system may end up generating aWM_LBUTTONDBLCLK
message and sending it to your hidden window, which you can then process in that window'sWndProc
(though I don't have a lot of experience with hooking so I don't know if this is possible).您是否在返回自己的结果之前调用 CallNextHookEx() - 根据 MSDN 的文档 MouseProc 强烈建议您调用它,因为当您返回自己的结果时,您会阻止调用其他挂钩。
您是否考虑过使用低级鼠标挂钩?它不需要将您的 DLL 注入到被挂钩的进程中,而且我发现它是一个更一致、更强大的挂钩(尽管如果编码不当,会占用更多资源)——特别是在侦听某些遗留应用程序中的点击时(有一个用古老的delphi编码的)并点击通过终端服务器(citrix)提供的应用程序。
低级别鼠标挂钩的唯一问题是它们本身不接收双击 - 这意味着您必须在注册表中查询“DoubleClickSpeed”,然后在触发双击之前检查该间隔内的两个鼠标按下事件。
Are you calling CallNextHookEx() before returning your own result - according to MSDN's documentation MouseProc it is highly recommended that you call it since when you return your own result you prevent other hooks from being called.
Have you considered using a low level mouse hook? It doesn't require your DLL to be injected into the process being hooked and I find it to be a more consistent and powerful hook (albeit more resource intensive if not coded appropriately) - especially when listening for clicks in some legacy applications (there was one that was coded in ancient delphi) and clicks in applications served via terminal servers (citrix).
The only issue with low level mouse hooks is that they don't receive double clicks per se - which means you have to query the registry for the 'DoubleClickSpeed' and then check for two mouse down events within that interval before triggering a double click.