C#中使用全局鼠标Hook实现全局双击动作捕获

相关参考文档:

http://www.cnblogs.com/michaelxu/archive/2006/09/22/511557.html

http://www.cnblogs.com/Johness/archive/2012/12/28/2837977.html

http://support.microsoft.com/default.aspx?scid=kb;en-us;318804

使用Low-level的钩子可以实现全局捕获相关动作,微软提供的有WH_MOUSE_LL和WH_KEYBOARD_LL这两个Low-level的钩子来实现对全局鼠标和全局键盘的捕获,配合SetWindowsHookEx,就可以将具体的钩子挂在到全局。

网上很多例子中,对于鼠标双击的动作捕获,都是认为可以捕获WM_LBUTTONDBLCLK这个消息,通过该消息来设定是否为双击,但实际挂在钩子后,Windows并不会直接捕获到WM_LBUTTONDBLCLK这个消息,而是两次WM_LBUTTONDOWN消息,因此,如果要实现双击的捕获,可考虑计算两次点击的时间间隔,和系统的双击时间间隔进行比较,从而判定是否为双击。

代码中引入系统的双击时间

[DllImport("user32.dll")]
public static extern int GetDoubleClickTime();

设定一个静态变量存储上一次点击的时间,以及一个静态变量存储具体的点击数

static DateTime lastClickTime;
static clickCount;

鼠标钩子回调函数中通过计算两次点击的时间间隔来区分双击与否,合理利用clickCount来避免三次快速点击时候被识别为两次双击

private int CallBackMouseHookProc(int nCode, int wParam, IntPtr lParam)
{
    if (nCode < 0)
    {
        CallNextHookEx(mshHook, nCode, wParam, lParam);
    }

    MOUSEHOOKSTRUCT mouseHookStruct = (MOUSEHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MOUSEHOOKSTRUCT));
    MouseButtons mouseButton = MouseButtons.None;

    switch (wParam)
    {
        case (int)MsgType.WM_LBUTTONDOWN:
            mouseButton = MouseButtons.Left;
            break;
        case (int)MsgType.WM_RBUTTONDOWN:
            mouseButton = MouseButtons.Right;
            break;
        case (int)MsgType.WM_MOUSEMOVE:
            clickCount = 0;
            break;
        default:
            break;
    }

    if (mouseButton == MouseButtons.Left)
    {
        System.TimeSpan deltaMs = DateTime.Now - lastClickTime;
        lastClickTime = DateTime.Now;

        if (deltaMs.TotalMilliseconds <= GetDoubleClickTime())
        {
            clickCount++;
        }
        else
        {
            clickCount = 1;
        }

        if (clickCount == 2)
        {
            MouseEventArgs e = new MouseEventArgs(
                mouseButton,
                clickCount,
                mouseHookStruct.pt.x,
                mouseHookStruct.pt.y,
                0);

            clickCount = 0;
            OnMouseDoubleClick(this, e);
        }
    }

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

更精确的还需要当鼠标移动时候则取消上一次的计算,不计入双击点击中

原文地址:https://www.cnblogs.com/wantoo/p/3949939.html