如何检测鼠标点击?

14

如何在Windows上检测鼠标点击?(XP/Vista/7) 例如,当我的应用程序正在运行时,它将检测用户是否单击了某些东西(不是在该应用程序的UI上而是在Windows UI上)。如果是,则执行另一个进程。

我不知道这是否可能,希望有人能给我一些指导。

谢谢!


这需要一个低级别的鼠标钩子,不是一个好的初学者项目。请谷歌搜索“+setwindowshookex +wh_mouse_ll”。否则,随意的鼠标点击启动进程没有什么意义。使用Windows Forms或WPF项目创建自己的用户界面。 - Hans Passant
这个问题太笼统了。你应该研究一些 UI 技术,比如 WPF 或 Winforms。 - Amittai Shapira
1
@Amittai:我认为这不是他们想要做的。他们不想要当前应用程序的鼠标事件... - Merlyn Morgan-Graham
3个回答

21
如果您想拦截任何鼠标点击、移动、滚轮点击等,您需要编写一个鼠标钩子。这是我所知道的唯一一种在自己的应用程序之外跟踪鼠标活动的方法。如果您想安装一个钩子,您需要从User32.dll文件中导入SetWindowsHookEx(...)函数。它涉及到Interop(PInvoke),您需要导入(DllImport)一些函数。
这是Microsoft关于如何在C#中实现此功能的官方文档: 如何在Visual C# .NET中设置Windows钩子 为了完整起见,我在这里总结一下:
从SetWindowsHookEx函数开始:
[DllImport("user32.dll",CharSet=CharSet.Auto,
 CallingConvention=CallingConvention.StdCall)]
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, 
IntPtr hInstance, int threadId);

现在您可以设置您的钩子。例如:
public class Form1
{
    static int hHook = 0;
    public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
    HookProc MouseHookProcedure;

    private void ActivateMouseHook_Click(object sender, System.EventArgs e)
    {
        if(hHook == 0)
        {
            MouseHookProcedure = new HookProc(Form1.MouseHookProc);
            hHook = SetWindowsHookEx(WH_MOUSE, 
                             MouseHookProcedure,
                             (IntPtr) 0,
                             AppDomain.GetCurrentThreadId());
        }
    }
}

不要忘记之后解除它的挂钩。你需要另一个 DllImport 来做这件事:
[DllImport("user32.dll",CharSet=CharSet.Auto,
CallingConvention=CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(int idHook);

private void DeactivateMouseHook_Click(object sender, System.EventArgs e)
{
    bool ret = UnhookWindowsHookEx(hHook);
}    

您可以使用HookProc委托(MouseHookProcedure)来捕获鼠标活动。这涉及到一些封送以便捕获数据。
[StructLayout(LayoutKind.Sequential)]
public class POINT 
{
    public int x;
    public int y;
}

[StructLayout(LayoutKind.Sequential)]
public class MouseHookStruct 
{
    public POINT pt;
    public int hwnd;
    public int wHitTestCode;
    public int dwExtraInfo;
}

public static int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{          
    MouseHookStruct MyMouseHookStruct = (MouseHookStruct)
        Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));

    // You can get the coördinates using the MyMouseHookStruct.
    // ...       
    return CallNextHookEx(hHook, nCode, wParam, lParam); 
}

不要忘记在钩子链中调用下一个项(CallNextHookEx)!
[DllImport("user32.dll",CharSet=CharSet.Auto,      
 CallingConvention=CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook, int nCode, 
IntPtr wParam, IntPtr lParam);

PS:您也可以对键盘执行相同的操作。

这段代码今天在Win10上是否能正常工作,因为HookProc不再在User32.dll中,也不再被识别,似乎已经移动到了winuser.dll https://learn.microsoft.com/en-us/windows/win32/api/winuser/nc-winuser-hookproc @Christophe Geers - lupaulus
@lupaulus 可能是可以的,这个答案已经有9年了,比Windows 10早4年。我建议查阅微软文档。 - Christophe Geers

6

虽然Christophe Geers的解决方案可以帮助您捕获鼠标事件,但它并不能为此问题提供完整的解决方案。 Edward想知道如何获取点击事件。

要获取点击事件,请使用Christophe Geers提供的解决方案。 并添加/编辑以下内容:

enum MouseMessages
{
    WM_LBUTTONDOWN = 0x0201,
    WM_LBUTTONUP = 0x0202,
    WM_MOUSEMOVE = 0x0200,
    WM_MOUSEWHEEL = 0x020A,
    WM_RBUTTONDOWN = 0x0204,
    WM_RBUTTONUP = 0x0205
}

public static int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
    //Marshall the data from the callback.
    MouseHookStruct MyMouseHookStruct = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));

    if (nCode >= 0 &&
        MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
    {
        // Do something here
    }
    return CallNextHookEx(hookHandle, nCode, wParam, lParam);
}

6

第二个链接已经失效,404。 - delroh
1
不要发布仅包含链接的答案。 - Enigmativity

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接