C# 是否有一种方法可以为windows窗体中的特定按钮钩住鼠标事件

C# 是否有一种方法可以为windows窗体中的特定按钮钩住鼠标事件,c#,c++,winapi,C#,C++,Winapi,我想从特定窗口中的特定按钮钩住WM_MOUSEDOWN和WM_MOUSEUP事件。我想SetWindowsHookEx会钩住我想要的消息。FindWindowEx将帮助我找到要捕获这些事件的窗口句柄 我只是不知道如何让它从特定的窗口句柄中为我提供事件。或者如何确定消息应该使用什么句柄 任何有这方面经验的人,我都会非常感激 编辑 或者将代码转换为C#中的Spy++工具或ManagedSpy的工作副本或类似的东西。我想学习如何浏览窗口句柄层次结构,并从中钩住窗口事件。您不能仅从单个窗口句柄中创建事件

我想从特定窗口中的特定按钮钩住WM_MOUSEDOWN和WM_MOUSEUP事件。我想SetWindowsHookEx会钩住我想要的消息。FindWindowEx将帮助我找到要捕获这些事件的窗口句柄

我只是不知道如何让它从特定的窗口句柄中为我提供事件。或者如何确定消息应该使用什么句柄

任何有这方面经验的人,我都会非常感激

编辑

或者将代码转换为C#中的Spy++工具或ManagedSpy的工作副本或类似的东西。我想学习如何浏览窗口句柄层次结构,并从中钩住窗口事件。

您不能仅从单个窗口句柄中创建事件,但您可以自己筛选它。如果使用的是
WH_CALLWNDPROC
WH_CALLWNDPROCRET
(需要使用它来获取感兴趣的鼠标消息),则和的
lParam
值是一个包含处理消息控件的窗口句柄的结构

因此,在您的
设置WindowsHookex
回拨中,您只需检查消息是否针对您正在筛选的窗口

例如:

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\u CALLWNDPROCRET

setwindowshookx
可以用于钩住特定线程或所有线程。你不能钩住一个特定的把手。您可以获取windows窗体应用程序的特定线程或所有线程并钩住它们,但这并不能解决您的问题,这只是性能方面的考虑

MouseProc
的回调中,您可以使用
wParam
过滤事件
WM\u LBUTTONDOWN
WM\u LBUTTONUP

您可以从
lParam

MOUSEHOOKSTRUCT * pMouseHookStruct = (MOUSEHOOKSTRUCT *) lParam;
HWMD hWnd = pMouseHookStruct->hwnd;
hwnd
可以获得该窗口的所有详细信息,并且可以检查它是否与windows窗体窗口相同

如果只需要特定按钮的鼠标事件,可以从鼠标单击点获取UI对象详细信息,并相应地过滤事件(使用
UIAutomation


您可以从
IUIAutomationeElement

获取
按钮名称
矩形坐标
热键
等。对于
调用WndProc
钩子,LPRAM是否始终是CWP结构?是的。一个
WH_CALLWNDPROCRET
hook使用
CWPRETSTRUCT
代替。所以现在你的每个答案都有相互竞争的结构。。。这些是相同的结构吗?@VolureDarkAngel:这是两种不同的方法,一种是使用WH_鼠标钩子捕获所有鼠标事件,另一种是捕获所有进入窗口的Windows消息事件。您知道一个好地方可以获取有关低级钩子的更多信息吗。最佳实践和方法等等?你使用Whu鼠标,我仍在使用它,但据我所知,你不能使用Whu鼠标来获取本地信息(你要寻找的hwnd)。根据我现在的理解,唯一的方法是创建一个.dll文件。
CoCreateInstance(__uuidof(CUIAutomation), NULL, CLSCTX_INPROC_SERVER, __uuidof(IUIAutomation), (void**)&pAutomation);

pAutomation->ElementFromPoint(*pPoint, &pIUIAutomationElement);