• 禁用 全局快捷键


    在给软件添加快捷键时,经常遇到其它软件或者系统已设置的快捷键,导致功能冲突。

    HotKey函数

    下面介绍一个user32.dll的RegisterHotKey以及UnregisterHotKey热键处理的函数

    注册热键 RegisterHotKey function 

    BOOL RegisterHotKey(
       HWND hWnd, //响应热键的窗口句柄,如果为空,则注册到调用线程上
       Int id, //热键的唯一标识
       UINT fsModifiers, //热键的辅助按键
       UINT vk //热键的键值
    );

    解除注册热键UnregisterHotKey function  

    BOOL WINAPI UnregisterHotKey( 
       HWND hWnd,//热键注册的窗口 
       int  id//要解除注册的热键ID 
    );

    添加热键注册和注销函数

    流程:

    Register方法 -  注册user32.dll函数RegisterHotKey以禁用全局键,并在缓存内添加禁用记录

    ProcessHotKey方法 - 外界全局键调用时,调用回调函数

      1     public class HotKeys
      2     {
      3         #region 注册快捷键
      4 
      5         /// <summary>
      6         /// 注册快捷键
      7         /// </summary>
      8         /// <param name="modifiers"></param>
      9         /// <param name="key"></param>
     10         public void Register(int modifiers, Keys key)
     11         {
     12             Register(IntPtr.Zero, modifiers, key);
     13         }
     14         /// <summary>
     15         /// 注册快捷键
     16         /// </summary>
     17         /// <param name="hWnd"></param>
     18         /// <param name="modifiers"></param>
     19         /// <param name="key"></param>
     20         /// <param name="callBack"></param>
     21         public void Register(IntPtr hWnd, int modifiers, Keys key, HotKeyCallBackHanlder callBack = null)
     22         {
     23             var registerRecord = _hotkeyRegisterRecords.FirstOrDefault(i => i.IntPtr == hWnd && i.Modifiers == modifiers && i.Key == key);
     24             if (registerRecord != null)
     25             {
     26                 UnregisterHotKey(hWnd, registerRecord.Id);
     27                 _hotkeyRegisterRecords.Remove(registerRecord);
     28             }
     29             int id = registerId++;
     30             if (!RegisterHotKey(hWnd, id, modifiers, key))
     31                 throw new Exception("注册失败!");
     32             _hotkeyRegisterRecords.Add(new HotkeyRegisterRecord()
     33             {
     34                 Id = id,
     35                 IntPtr = hWnd,
     36                 Modifiers = modifiers,
     37                 Key = key,
     38                 CallBack = callBack
     39             });
     40         }
     41 
     42         #endregion
     43 
     44         #region 注销快捷键
     45 
     46         /// <summary>
     47         /// 注销快捷键
     48         /// </summary>
     49         /// <param name="hWnd"></param>
     50         /// <param name="modifiers"></param>
     51         /// <param name="key"></param>
     52         public void UnRegister(IntPtr hWnd, int modifiers, Keys key)
     53         {
     54             var registerRecord = _hotkeyRegisterRecords.FirstOrDefault(i => i.IntPtr == hWnd && i.Modifiers == modifiers && i.Key == key);
     55             if (registerRecord != null)
     56             {
     57                 UnregisterHotKey(hWnd, registerRecord.Id);
     58                 _hotkeyRegisterRecords.Remove(registerRecord);
     59             }
     60         }
     61         /// <summary>
     62         /// 注销快捷键
     63         /// </summary>
     64         /// <param name="modifiers"></param>
     65         /// <param name="key"></param>
     66         public void UnRegister(int modifiers, Keys key)
     67         {
     68             var registerRecord = _hotkeyRegisterRecords.FirstOrDefault(i => i.IntPtr == IntPtr.Zero && i.Modifiers == modifiers && i.Key == key);
     69             if (registerRecord != null)
     70             {
     71                 UnregisterHotKey(IntPtr.Zero, registerRecord.Id);
     72                 _hotkeyRegisterRecords.Remove(registerRecord);
     73             }
     74         }
     75         /// <summary>
     76         /// 注销快捷键
     77         /// </summary>
     78         /// <param name="hWnd"></param>
     79         public void UnRegister(IntPtr hWnd)
     80         {
     81             var registerRecords = _hotkeyRegisterRecords.Where(i => i.IntPtr == hWnd);
     82             //注销所有
     83             foreach (var registerRecord in registerRecords)
     84             {
     85                 UnregisterHotKey(hWnd, registerRecord.Id);
     86                 _hotkeyRegisterRecords.Remove(registerRecord);
     87             }
     88         }
     89 
     90         #endregion
     91 
     92         #region 快捷键消息处理
     93 
     94         // 快捷键消息处理
     95         public void ProcessHotKey(Message message)
     96         {
     97             ProcessHotKey(message.Msg, message.WParam);
     98         }
     99 
    100         /// <summary>
    101         /// 快捷键消息处理
    102         /// </summary>
    103         /// <param name="msg"></param>
    104         /// <param name="wParam">消息Id</param>
    105         public void ProcessHotKey(int msg, IntPtr wParam)
    106         {
    107             if (msg == 0x312)
    108             {
    109                 int id = wParam.ToInt32();
    110                 var registerRecord = _hotkeyRegisterRecords.FirstOrDefault(i => i.Id == id);
    111                 registerRecord?.CallBack?.Invoke();
    112             }
    113         }
    114 
    115         #endregion
    116 
    117         #region MyRegion
    118 
    119         //引入系统API
    120         [DllImport("user32.dll")]
    121         static extern bool RegisterHotKey(IntPtr hWnd, int id, int modifiers, Keys vk);
    122         [DllImport("user32.dll")]
    123         static extern bool UnregisterHotKey(IntPtr hWnd, int id);
    124 
    125         //标识-区分不同的快捷键
    126         int registerId = 10;
    127         //添加key值注册字典,后续调用时有回调处理函数
    128         private readonly List<HotkeyRegisterRecord> _hotkeyRegisterRecords = new List<HotkeyRegisterRecord>();
    129         public delegate void HotKeyCallBackHanlder();
    130 
    131         #endregion
    132 
    133     }
    134 
    135     public class HotkeyRegisterRecord
    136     {
    137         public IntPtr IntPtr { get; set; }
    138         public int Modifiers { get; set; }
    139         public Keys Key { get; set; }
    140         public int Id { get; set; }
    141         public HotKeys.HotKeyCallBackHanlder CallBack { get; set; }
    142     }
    143     //组合控制键
    144     public enum HotkeyModifiers
    145     {
    146         Alt = 1,
    147         Control = 2,
    148         Shift = 4,
    149         Win = 8
    150     }
    View Code

    在上方的HotKeys类中,注册方法Register提供了一个回调函数,后续监听到外界全局键时,可以通知回调函数处理。

    参数WParam,是窗口响应时快捷键值,在winform和WPF窗口消息函数中都是有的。

    另,组合快捷键内部枚举类HotkeyModifiers,枚举值来自官网文档WM_HOTKEY message

    无感知禁用全局快捷键

    比如:禁用Ctrl+Alt+1、Ctrl+Alt+2、Ctrl+Alt+3、Ctrl+Alt+4(Windows桌面图标大小的调节快捷键)

    1     HotKeys hotKeys = new HotKeys();
    2     hotKeys.Register((int)HotkeyModifiers.Control, Keys.N);
    3     hotKeys.Register((int)HotkeyModifiers.Control + (int)HotkeyModifiers.Alt, Keys.D1);
    4     hotKeys.Register((int)HotkeyModifiers.Control + (int)HotkeyModifiers.Alt, Keys.D2);
    5     hotKeys.Register((int)HotkeyModifiers.Control + (int)HotkeyModifiers.Alt, Keys.D3);
    6     hotKeys.Register((int)HotkeyModifiers.Control + (int)HotkeyModifiers.Alt, Keys.D4);

    注:

    • 窗口句柄参数,如果提供空的话,则注册到调用线程上。
    • Keys类型在system.windows.Forms程序集下,如果是WPF的Key,可以使用KeyInterop将Wpf键值类型转换为Winform键值再调用此函数。

    无感知禁用全局快捷键后回调

    如果禁用全局快捷键的同时,外界触发快捷键时需要此程序回调处理,可以添加窗口消息处理:

    1. 新建一个类HotKeyHandleWindow,继承自Window

    • 窗口样式 - 高宽为0,窗口样式None
    • 添加热键注册的调用
    • 添加WndProc,处理窗口消息
     1     public class HotKeyHandleWindow : Window
     2     {
     3         private readonly HotKeys _hotKeys = new HotKeys();
     4         public HotKeyHandleWindow()
     5         {
     6             WindowStyle = WindowStyle.None;
     7             Width = 0;
     8             Height = 0;
     9             Loaded += (s, e) =>
    10             {
    11                 //这里注册了Ctrl+Alt+1 快捷键
    12                 _hotKeys.Register(new WindowInteropHelper(this).Handle,
    13                     (int)HotkeyModifiers.Control + (int)HotkeyModifiers.Alt, Keys.D1, CallBack);
    14             };
    15         }
    16         protected override void OnSourceInitialized(EventArgs e)
    17         {
    18             base.OnSourceInitialized(e);
    19             var hwndSource = PresentationSource.FromVisual(this) as HwndSource;
    20             hwndSource?.AddHook(new HwndSourceHook(WndProc));
    21         }
    22         public IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    23         {
    24             //窗口消息处理函数
    25             _hotKeys.ProcessHotKey(msg, wParam);
    26             return hwnd;
    27         }
    28         //按下快捷键时被调用的方法
    29         public void CallBack()
    30         {
    31         }
    32     }

    2. 调用窗口类:

    1     var hotKeyHandleWindow = new HotKeyHandleWindow();
    2     hotKeyHandleWindow.Show();
    3     hotKeyHandleWindow.Hide();

    以上有回调响应,但是也是无感知的。

    Demo: https://github.com/Kybs0/DiableGlobalShortcuts

  • 相关阅读:
    设计模式(二十三)—— 模板方法
    设计模式(二十二)—— 策略模式
    设计模式(二十一)—— 状态模式
    设计模式(二十)—— 观察者模式
    设计模式(十九)—— 备忘录模式
    设计模式(十八)—— 中介者模式
    设计模式(十七)—— 迭代器模式
    设计模式(十六)—— 解释器模式
    设计模式(十五)—— 命令模式
    设计模式(十四)—— 职责链模式
  • 原文地址:https://www.cnblogs.com/kybs0/p/12558056.html
Copyright © 2020-2023  润新知