有没有办法为 Windows 窗体中的特定按钮挂钩鼠标事件
Posted
技术标签:
【中文标题】有没有办法为 Windows 窗体中的特定按钮挂钩鼠标事件【英文标题】:Is there a way to hook mouse events for a specific button in a windows form 【发布时间】:2011-10-14 00:17:12 【问题描述】:我想从特定窗口内的特定按钮挂钩 WM_MOUSEDOWN 和 WM_MOUSEUP 事件。我在想 SetWindowsHookEx 会钩住我想要的消息。 FindWindowEx 将帮助我找到要从中捕获这些事件的窗口句柄。
我只是不知道如何让它给我来自特定窗口句柄的事件。或者如何确定消息应该发送到哪个句柄。
其他有这方面经验的人,我将不胜感激
编辑
也可以选择 C# 中的 Spy++ 工具的代码或 ManagedSpy 的工作副本或类似的东西。我想学习导航窗口句柄层次结构并从中挂钩窗口事件。
【问题讨论】:
您使用 WH_MOUSE,我仍在使用它,但据我了解,您无法使用 WH_MOUSE_LL 获取本地信息(您要查找的 hwnd)。根据我现在的理解,唯一的方法是创建一个 .dll 文件。 【参考方案1】:您不能让SetWindowsHookEx 只为您提供来自单个窗口句柄的事件,但您可以自己过滤它。如果您使用WH_CALLWNDPROC
或WH_CALLWNDPROCRET
(您需要使用它们来获取您感兴趣的鼠标消息),则CallWndProc 和CallWndRetProc 的lParam
值是一个包含窗口句柄的结构处理消息的控件。
因此,在您的SetWindowsHookEx
回调中,您只需检查该消息是否适用于您正在过滤的窗口。
例如:
static HWND s_hWndButton;
.....
SetWindowsHookEx(WH_CALLWNDPROC, ButtonHookProc, ....);
.....
LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
if (nCode >= 0)
CWPSTRUCT* cp = (CWPSTRUCT*)lParam;
if (cp->hWnd == s_hWndButton)
if (cp->Msg == WM_MOUSEUP || cp->Msg == WM_MOUSEDOWN)
// Your logic goes here
Return CallNextHookEx(NULL, nCode, wParam, lParam);
几乎相同的逻辑适用于WH_CALLWNDPROCRET
【讨论】:
lparam 总是 CWPSTRUCT 吗? 仅适用于WH_CALLWNDPROC
挂钩,是的。 WH_CALLWNDPROCRET
挂钩使用 CWPRETSTRUCT
代替。【参考方案2】:
SetWindowsHookEx
可用于挂钩特定线程或所有线程。您不能钩住特定的手柄。您可以获取 windows 窗体应用程序的特定线程或所有线程并挂钩它们,但这并不能解决您的问题,这只是性能考虑。
在MouseProc
的回调中,您可以使用wParam
过滤事件WM_LBUTTONDOWN
、WM_LBUTTONUP
。
您可以从lParam
获取此鼠标事件所指向的窗口的句柄
MOUSEHOOKSTRUCT * pMouseHookStruct = (MOUSEHOOKSTRUCT *) lParam;
HWMD hWnd = pMouseHookStruct->hwnd;
从hwnd
你可以得到窗口的所有细节,你可以检查它是否是同一个窗体窗口。
如果您只想要特定按钮的鼠标事件,您可以从鼠标点击点获取 UI 对象详细信息并相应地过滤事件(使用 UIAutomation
)
CoCreateInstance(__uuidof(CUIAutomation), NULL, CLSCTX_INPROC_SERVER, __uuidof(IUIAutomation), (void**)&pAutomation);
pAutomation->ElementFromPoint(*pPoint, &pIUIAutomationElement);
您可以从IUIAutomationElement
获取button name
、rect coordinates
、hot keys
等
【讨论】:
所以现在你的每个答案都有竞争结构......这些结构相同吗? @VolureDarkAngel:这是两种不同的方法,一种是使用 WH_MOUSE 钩子捕获所有鼠标事件,另一种是捕获所有进入窗口的 Windows 消息事件 你知道获得更多关于低级挂钩的信息的好地方吗?最佳实践和方法之类的?以上是关于有没有办法为 Windows 窗体中的特定按钮挂钩鼠标事件的主要内容,如果未能解决你的问题,请参考以下文章
在 C#/Windows 窗体中检测应用程序启动时的 shift 键
如何对 SVN 中的特定文件夹使用预提交挂钩(Windows 批处理文件)?