David
发布于 2014-09-22 / 6 阅读 / 0 评论 / 0 点赞

C# 實現全局熱鍵 – 注册热键

續上篇[su_button url="https://akru.plus/archives/282" target="blank" style="flat" background="#2db0ef"]鍵盤消息鉤子[/su_button] 有時候微軟幫我們做了很多,也想到了很多,那就不要浪費別人一番苦心,好好利用。 先上管理熱鍵的類,示例代碼的註釋是必須的。
    class HotKey
    {
        #region API
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool RegisterHotKey(IntPtr hWnd, int id, HotkeyModifiers fsModifiers, Keys vk);

        [DllImport("user32.dll")]
        static extern bool UnregisterHotKey(IntPtr hWnd, int id);
        #endregion

        /// <summary>
        /// 組合按鍵
        /// </summary>
        public enum HotkeyModifiers
        {
            MOD_ALT = 0x1,
            MOD_CONTROL = 0x2,
            MOD_SHIFT = 0x4,
            MOD_WIN = 0x8
        }

        const int WM_HOTKEY = 0x312;
        /// <summary>
        /// 起始值
        /// </summary>
        static int keyid = 1;

        static Dictionary<int, KeyInfo> keymap = new Dictionary<int, KeyInfo>();
        /// <summary>
        /// 存放熱鍵回調函數和窗口句柄
        /// </summary>
        private struct KeyInfo
        {
            public KeyInfo(HotKeyCallBackHanlder callBack, IntPtr Hwnd)
            {
                this.CallBack = callBack;
                this.hWnd = Hwnd;
            }
            public HotKeyCallBackHanlder CallBack;
            public IntPtr hWnd;
        }

        public delegate void HotKeyCallBackHanlder();

        /// <summary> 
        /// 注册快捷键 
        /// </summary> 
        /// <param name="hWnd">持有快捷键窗口的句柄</param> 
        /// <param name="fsModifiers">组合键</param> 
        /// <param name="vk">快捷键的虚拟键码</param> 
        /// <param name="callBack">回调函数</param> 
        public static bool Regist(IntPtr hWnd, HotkeyModifiers fsModifiers, Keys vk, HotKeyCallBackHanlder callBack)
        {
            int id = keyid;
           
            if (!RegisterHotKey(hWnd, id, fsModifiers, vk))
            {
                return false;
            }
            
            keymap[id] = new KeyInfo(callBack, hWnd);
            Debug.Print("註冊热键:{0}", keyid.ToString());
            keyid++;
            return true;
        }


        /// <summary> 
        /// 注销快捷键 
        /// </summary> 
        /// <param name="hWnd">持有快捷键窗口的句柄</param> 
        /// <param name="callBack">回调函数</param> 
        public static void UnRegist(IntPtr hWnd, HotKeyCallBackHanlder callBack)
        {
            int i = -1;
            foreach (KeyValuePair<int, KeyInfo> var in keymap)
            {
                if (var.Value.hWnd == hWnd && var.Value.CallBack == callBack)
                    UnregisterHotKey(hWnd, var.Key); i = var.Key; break;
            }
            Debug.Print("注销热键:{0}", i.ToString());
            if (i > -1)
            {
                keymap.Remove(i);
                if (i < keyid)
                { keyid = i; }
               
                
            }
        }

        /// <summary> 
        /// 快捷键消息处理 
        /// </summary> 
        public static void ProcessHotKey(System.Windows.Forms.Message m)
        {
            if (m.Msg == WM_HOTKEY)
            {
                int id = m.WParam.ToInt32();
                KeyInfo ki;
                if (keymap.TryGetValue(id, out ki))
                {
                    ki.CallBack();
                }
            }
        }
        /// <summary>
        /// 註銷所有熱鍵
        /// </summary>
        public static void UnRegistAll()
        {
            foreach (KeyValuePair<int, KeyInfo> var in keymap)
            {
                UnregisterHotKey(var.Value.hWnd, var.Key);
            }
        }

    }
裡邊維護熱鍵ID的keyid隨意就好,強迫症的我必須要排好,不能中間缺一個。 對於需要註冊多個熱鍵,必須要有專門的類進行維護,註冊的時候直接調用Regist,註銷單一熱鍵就調用UnRegist。 為了保證程序關閉時註銷所有熱鍵,所以還有個註銷所有熱鍵的功能,以防萬一。 循例也要上調用代碼
            //Ctrl+Alt+S
            bool result = HotKey.Regist(this.Handle, HotKey.HotkeyModifiers.MOD_CONTROL | HotKey.HotkeyModifiers.MOD_ALT, Keys.S, Save);
            if (result == false)
            {
                this.Text = "註冊熱鍵失敗";
            }
            //Ctrl+S
            result = HotKey.Regist(this.Handle, HotKey.HotkeyModifiers.MOD_CONTROL,Keys.S, Save);
            if (result == false)
            {
                this.Text = "註冊熱鍵失敗";
            }
Save就是當用戶按下你所設定按鍵後觸發的回調函數,至於裡面是什麼代碼,自己加個信息框什麼的。
//清除指定窗口句柄下的指定熱鍵,只需要傳入對應的回調函數即可
HotKey.UnRegist(this.Handle, Save);
//清除所有熱鍵
HotKey.UnRegistAll();
註冊+管理全局熱鍵就OK了,下一篇文章就說程序內的熱鍵,不是全局。