相關參考文檔:
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); }
更精確的還需要當鼠標移動時候則取消上一次的計算,不計入雙擊點擊中
