禁用 全局快捷键

Posted kybs0

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了禁用 全局快捷键相关的知识,希望对你有一定的参考价值。

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

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         //引入系统API
 4         [DllImport("user32.dll")]
 5         static extern bool RegisterHotKey(IntPtr hWnd, int id, int modifiers, Keys vk);
 6         [DllImport("user32.dll")]
 7         static extern bool UnregisterHotKey(IntPtr hWnd, int id);
 8 
 9         //标识-区分不同的快捷键
10         int keyid = 10;
11         //添加key值注册字典,后续调用时有回调处理函数
12         Dictionary<int, HotKeyCallBackHanlder> keyDict = new Dictionary<int, HotKeyCallBackHanlder>();   
13         public delegate void HotKeyCallBackHanlder();
14 
15         //组合控制键
16         public enum HotkeyModifiers
17         {
18             Alt = 1,
19             Control = 2,
20             Shift = 4,
21             Win = 8
22         }
23 
24         //注册快捷键
25         public void Register(IntPtr hWnd, int modifiers, Keys vk, HotKeyCallBackHanlder callBack)
26         {
27             int id = keyid++;
28             if (!RegisterHotKey(hWnd, id, modifiers, vk))
29                 throw new Exception("注册失败!");
30             keyDict[id] = callBack;
31         }
32 
33         // 注销快捷键
34         public void UnRegister(IntPtr hWnd, HotKeyCallBackHanlder callBack)
35         {
36             foreach (KeyValuePair<int, HotKeyCallBackHanlder> var in keyDict)
37             {
38                 if (var.Value == callBack)
39                 {
40                     UnregisterHotKey(hWnd, var.Key);
41                     return;
42                 }
43             }
44         }
45 
46         // 快捷键消息处理
47         public void ProcessHotKey(Message message)
48         {
49             if (message.Msg == 0x312)
50             {
51                 int id = message.WParam.ToInt32();
52                 HotKeyCallBackHanlder callback;
53                 if (keyDict.TryGetValue(id, out callback))
54                     callback();
55             }
56         }
57         //快捷键消息处理
58         public void ProcessHotKey(int msg, IntPtr wParam)
59         {
60             if (msg == 0x312)
61             {
62                 int id = wParam.ToInt32();
63                 HotKeyCallBackHanlder callback;
64                 if (keyDict.TryGetValue(id, out callback))
65                     callback();
66             }
67         }
68     }

在上方的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(IntPtr.Zero, (int)HotKeys.HotkeyModifiers.Control + (int)HotKeys.HotkeyModifiers.Alt, Keys.D1, () => { });
3     hotKeys.Register(IntPtr.Zero, (int)HotKeys.HotkeyModifiers.Control + (int)HotKeys.HotkeyModifiers.Alt, Keys.D2, () => { });
4     hotKeys.Register(IntPtr.Zero, (int)HotKeys.HotkeyModifiers.Control + (int)HotKeys.HotkeyModifiers.Alt, Keys.D3, () => { });
5     hotKeys.Register(IntPtr.Zero, (int)HotKeys.HotkeyModifiers.Control + (int)HotKeys.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)HotKeys.HotkeyModifiers.Control + (int)HotKeys.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();

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

以上是关于禁用 全局快捷键的主要内容,如果未能解决你的问题,请参考以下文章

VS code自定义用户代码片段snippet

C#如何全局禁用键盘的回车键

在 KDE 中禁用全局 Ctrl-Alt-L 热键

如何禁用在android片段类中按下的后退按钮

VSCode 如何操作用户自定义代码片段(快捷键)

在 Firebase 中禁用自动活动跟踪