閑扯:
前幾日,一個朋友問我如何實現按 F1 鍵實現粘貼(Ctrl+V)功能,百度了一個方法,發給他,他看不懂(已經是 Boss 的曾經的碼農),我就做了個Demo給他參考。今日得空,將 Demo 整理一下,做為收集,也給大家一個參考。
Begin:
注冊系統熱鍵,.net 類庫好像沒有提供現成的方法,需要使用系統提供的 DLL。
微軟將許多常用的系統函數都封裝在 user32.dll 中,注冊系統熱鍵使用到的 RegisterHotKey 函數和 UnregisterHotKey 函數也在該 DLL 文件中,所以我們需要將這兩個方法映射到 C# 類中。下面代碼封裝了這兩個方法,並做一些簡單的封裝,如下:
1 using System; 2 using System.Text; 3 using System.Runtime.InteropServices; 4 using System.Windows.Forms; 5 6 public class SystemHotKey 7 { 8 /// <summary> 9 /// 如果函數執行成功,返回值不為0。 10 /// 如果函數執行失敗,返回值為0。要得到擴展錯誤信息,調用GetLastError。 11 /// </summary> 12 /// <param name="hWnd">要定義熱鍵的窗口的句柄</param> 13 /// <param name="id">定義熱鍵ID(不能與其它ID重復)</param> 14 /// <param name="fsModifiers">標識熱鍵是否在按Alt、Ctrl、Shift、Windows等鍵時才會生效</param> 15 /// <param name="vk">定義熱鍵的內容</param> 16 /// <returns></returns> 17 [DllImport("user32.dll", SetLastError = true)] 18 public static extern bool RegisterHotKey(IntPtr hWnd, int id, KeyModifiers fsModifiers, Keys vk); 19 20 /// <summary> 21 /// 注銷熱鍵 22 /// </summary> 23 /// <param name="hWnd">要取消熱鍵的窗口的句柄</param> 24 /// <param name="id">要取消熱鍵的ID</param> 25 /// <returns></returns> 26 [DllImport("user32.dll", SetLastError = true)] 27 public static extern bool UnregisterHotKey(IntPtr hWnd, int id); 28 29 /// <summary> 30 /// 輔助鍵名稱。 31 /// Alt, Ctrl, Shift, WindowsKey 32 /// </summary> 33 [Flags()] 34 public enum KeyModifiers { None = 0, Alt = 1, Ctrl = 2, Shift = 4, WindowsKey = 8 } 35 36 /// <summary> 37 /// 注冊熱鍵 38 /// </summary> 39 /// <param name="hwnd">窗口句柄</param> 40 /// <param name="hotKey_id">熱鍵ID</param> 41 /// <param name="keyModifiers">組合鍵</param> 42 /// <param name="key">熱鍵</param> 43 public static void RegHotKey(IntPtr hwnd, int hotKeyId, KeyModifiers keyModifiers, Keys key) 44 { 45 if (!RegisterHotKey(hwnd, hotKeyId, keyModifiers, key)) 46 { 47 int errorCode = Marshal.GetLastWin32Error(); 48 if (errorCode == 1409) 49 { 50 MessageBox.Show("熱鍵被占用 !"); 51 } 52 else 53 { 54 MessageBox.Show("注冊熱鍵失敗!錯誤代碼:" + errorCode); 55 } 56 } 57 } 58 59 /// <summary> 60 /// 注銷熱鍵 61 /// </summary> 62 /// <param name="hwnd">窗口句柄</param> 63 /// <param name="hotKey_id">熱鍵ID</param> 64 public static void UnRegHotKey(IntPtr hwnd, int hotKeyId) 65 { 66 //注銷指定的熱鍵 67 UnregisterHotKey(hwnd, hotKeyId); 68 } 69 70 }
(這個類是網上搜到的,這里借用一下。。。在此對原作者表示感謝!)
上面這個類中,只需要使用兩個靜態方法 RegHotKey 和 UnRegHotKey 來注冊和注銷熱鍵即可。
這里有一點需要注意一下:這兩個方法需要一個窗口的句柄來綁定系統熱鍵消息,也就是說,當用戶按下注冊過的熱鍵以后,系統會將按鍵消息發送給指定窗口。
RegHotKey 方法有四個參數,第一個是窗口句柄,第二個是自定義的熱鍵ID,第三個是組合鍵,比如Ctrl、Alt、Shift等,如果沒有,就是None,第四個就是指定的熱鍵了。
UnRegHotKey 方法只需要窗口句柄和熱鍵ID,就可以將該熱鍵注銷。
然后,創建一個窗體,在代碼視圖中添加如下代碼:
private const int WM_HOTKEY = 0x312; //窗口消息:熱鍵 private const int WM_CREATE = 0x1; //窗口消息:創建 private const int WM_DESTROY = 0x2; //窗口消息:銷毀 private const int HotKeyID = 1; //熱鍵ID(自定義) protected override void WndProc(ref Message msg) { base.WndProc(ref msg); switch (msg.Msg) { case WM_HOTKEY: //窗口消息:熱鍵 int tmpWParam = msg.WParam.ToInt32(); if (tmpWParam == HotKeyID) { System.Windows.Forms.SendKeys.Send("^v"); } break; case WM_CREATE: //窗口消息:創建 SystemHotKey.RegHotKey(this.Handle, HotKeyID, SystemHotKey.KeyModifiers.None, Keys.F1); break; case WM_DESTROY: //窗口消息:銷毀 SystemHotKey.UnRegHotKey(this.Handle, HotKeyID); //銷毀熱鍵 break; default: break; } }
在上面代碼中,WM_HOTKEY、WM_CREATE、WM_DESTROY 三個常量的值是系統定義,不用關心。HotKeyID 是自定義的一個數值,用於在注冊了多個熱鍵的時候使用該數值來區分不同熱鍵處理邏輯,系統會在用戶觸發熱鍵時將該值做為參數傳遞給處理程序。
另外,上面代碼中重寫了一個系統方法 WndProc,這個方法叫“窗口過程”(參考百度百科),用於接收處理注冊到該窗體上的所有事件,包括窗體創建、窗體銷毀、系統熱鍵等等。該方法有一個 Message 結構體參數,該參數封裝了 Windows 消息的一些基本屬性,比如消息ID、參數等等。
上面代碼在該方法接收到窗口創建消息的時候注冊熱鍵 F1,並且在接收到窗口銷毀消息的時候注銷該熱鍵,並且在接收到系統熱鍵消息的時候,根據消息參數(熱鍵ID)來確認觸發我們想要的動作,比如這里的模擬用戶按下 Ctrl+V 鍵。
最后,運行該程序,就可以在任意應用程序里使用 F1 鍵完成 Ctrl+V 的效果了。
