全局热键工具类(GlobalHotkey)
【文 / 张赐荣】
1. 功能概述
全局热键工具类(GlobalHotkey)是一个用于注册全局热键的工具类。它允许你在你的应用程序中注册特定的键盘组合,以便在用户按下这些组合时触发相应的事件。此工具类提供了以下主要功能:
- 注册多个热键并定义每个热键的组合。
- 当用户按下注册的热键时,触发相应的事件。
- 跟踪热键按下的次数。
2. 如何使用
a. 注册热键
要注册热键,可以使用 RegisterHotkey
方法,该方法允许你指定修改键(如 Ctrl、Shift、Alt、Windows)和虚拟键(如 A、B、数字键等)的组合。示例:
int hotkeyId = GlobalHotkey.RegisterHotkey(ModifiedKeys.Ctrl | ModifiedKeys.Alt, VirtualKey.A);
if (hotkeyId > 0)
{
// 热键注册成功,可以执行相应操作
}
b. 注销热键
要注销之前注册的热键,可以使用 UnregisterHotkey
方法,并传入先前注册热键时返回的热键ID。示例:
bool isUnregistered = GlobalHotkey.UnregisterHotkey(hotkeyId);
if (isUnregistered)
{
// 热键注销成功
}
3. 多个热键绑定
可以多次调用 RegisterHotkey
方法来注册多个热键,每个热键都应具有唯一的热键ID。示例:
int hotkeyId1 = GlobalHotkey.RegisterHotkey(ModifiedKeys.Ctrl, VirtualKey.F1);
int hotkeyId2 = GlobalHotkey.RegisterHotkey(ModifiedKeys.Alt, VirtualKey.F2);
// 可以继续注册其他热键
4. 判断按键次数
当热键被按下时,会触发 HotkeyPressedEvent
事件。可以订阅这个事件来处理热键按下的情况,并获取按键的计数。示例:
GlobalHotkey.HotkeyPressedEvent += (sender, e) =>
{
// 处理按键事件,可以通过 HotkeyPressedEventArgs 获取按键相关信息
Console.WriteLine($"热键按下:{e.VirtualKey},按键次数:{e.PressedCount}");
};
5. 注意事项
- 在注册热键之前,确保你的应用程序处于消息循环状态(MessageLoop)。
- 每个热键的组合应该是独一无二的,避免冲突。
- 在不再需要使用热键时,及时进行注销操作。
6. 示例代码
下面是一个简单的示例代码,演示了如何注册热键并处理热键按下事件:
// 注册热键
int hotkeyId = GlobalHotkey.RegisterHotkey(ModifiedKeys.Ctrl, VirtualKey.F1);
// 处理热键按下事件
GlobalHotkey.HotkeyPressedEvent += (sender, e) =>
{
if (e.HotkeyId == hotkeyId)
{
// 处理 Ctrl + F1 按下事件
Console.WriteLine($"热键按下:{e.VirtualKey},按键次数:{e.PressedCount}");
}
};
全局热键工具类完整代码
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Dotnet.WinAPI.GlobalHotkey
{
public delegate void HotkeyPressedEventHandler(object sender, HotkeyPressedEventArgs e);
public static class GlobalHotkey
{
private static HotkeyMessageFilter _HotkeyMessageFilter = null;
private static readonly Dictionary<int, KeyData> HotkeyData = new Dictionary<int, KeyData>();
public static event HotkeyPressedEventHandler HotkeyPressedEvent;
[DllImport("user32.dll", EntryPoint = "RegisterHotKey")]
private static extern bool API_RegisterHotKey(IntPtr hWnd, int id, ModifiedKeys fsModifiers, VirtualKey vk);
[DllImport("user32.dll", EntryPoint = "UnregisterHotKey")]
private static extern bool API_UnregisterHotKey(IntPtr hWnd, int id);
public static int RegisterHotkey(ModifiedKeys mks, VirtualKey vk)
{
try
{
if (mks == ModifiedKeys.None && vk == VirtualKey.None)
{
return (-1);
}
if (!Application.MessageLoop)
{
return (-2);
}
if (_HotkeyMessageFilter is null)
{
_HotkeyMessageFilter = new HotkeyMessageFilter();
Application.AddMessageFilter(_HotkeyMessageFilter);
}
int hId = (((byte)mks) << 8) | (byte)vk;
UnregisterHotkey(hId);
int result = (API_RegisterHotKey(IntPtr.Zero, hId, mks, vk) ? hId : -1);
if (result > 0)
{
System.Windows.Forms.Timer keyTimer = new System.Windows.Forms.Timer() { Interval = SystemInformation.DoubleClickTime };
KeyData keyData = new KeyData() { KeyPressedCount = 0, KeyTimer = keyTimer };
HotkeyData[hId] = keyData;
keyTimer.Tick += (_s, _e) =>
{
keyTimer.Stop();
keyData.KeyPressedCount = 0;
};
}
return (result);
}
catch (Exception ex)
{
Debug.WriteLine(ex);
return (-3);
}
}
public static bool UnregisterHotkey(int hotkeyId)
{
try
{
bool res = API_UnregisterHotKey(IntPtr.Zero, hotkeyId);
if (res && HotkeyData.ContainsKey(hotkeyId))
{
HotkeyData[hotkeyId].KeyTimer.Stop();
HotkeyData.Remove(hotkeyId);
}
return (res);
}
catch (Exception ex)
{
Debug.WriteLine(ex);
return (false);
}
}
class HotkeyMessageFilter : IMessageFilter
{
private const int WM_HOTKEY = 786;
bool IMessageFilter.PreFilterMessage(ref Message m)
{
switch (m.Msg)
{
case WM_HOTKEY:
try
{
int hId = m.WParam.ToInt32();
if (!(HotkeyPressedEvent is null) && HotkeyData.ContainsKey(hId))
{
HotkeyData[hId].KeyTimer.Start();
HotkeyData[hId].KeyPressedCount++;
int lParam = m.LParam.ToInt32();
byte vk = (byte)(lParam >> 16);
byte mks = (byte)(lParam & 0Xffff);
HotkeyPressedEvent?.Invoke(this, new HotkeyPressedEventArgs(hId, (ModifiedKeys)mks, (VirtualKey)vk, HotkeyData[hId].KeyPressedCount));
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
return (true);
break;
}
return (false);
}
}
}
public class HotkeyPressedEventArgs : EventArgs
{
public int HotkeyId { get; }
public ModifiedKeys ModifiedKeys { get; }
public VirtualKey VirtualKey { get; }
public int PressedCount { get; }
public HotkeyPressedEventArgs(int hotkeyId, ModifiedKeys modifiedKeys, VirtualKey virtualKey, int pressedCount)
{
this.HotkeyId = hotkeyId;
this.ModifiedKeys = ModifiedKeys;
this.VirtualKey = virtualKey;
this.PressedCount = pressedCount;
}
public override string ToString()
{
return ($"{nameof(this.HotkeyId)}:{this.HotkeyId}, {nameof(this.ModifiedKeys)}:{this.ModifiedKeys}, {nameof(this.VirtualKey)}:{this.VirtualKey}, {nameof(this.PressedCount)}:{this.PressedCount}");
}
}
class KeyData
{
public int KeyPressedCount = 0;
public System.Windows.Forms.Timer KeyTimer = null;
}
[Flags]
public enum ModifiedKeys : byte
{
None = 0,
Alt = 1,
Ctrl = 2,
Shift = 4,
Windows = 8
}
public enum VirtualKey : uint
{
None = 0,
BackSpace = 8,
Tab = 9,
Clear = 12,
Enter = 13,
Pause = 19,
Caps = 20,
Escape = 27,
Space = 32,
PageUp = 33,
PageDown = 34,
End = 35,
Home = 36,
LeftArrow = 37,
UpArrow = 38,
RightArrow = 39,
DownArrow = 40,
PrintScreen = 44,
Insert = 45,
Delete = 46,
Zero = 48,
One = 49,
Two = 50,
Three = 51,
Four = 52,
Five = 53,
Six = 54,
Seven = 55,
Eight = 56,
Nine = 57,
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90,
Apps = 93,
NumPad0 = 96,
NumPad1 = 97,
NumPad2 = 98,
NumPad3 = 99,
NumPad4 = 100,
NumPad5 = 101,
NumPad6 = 102,
NumPad7 = 103,
NumPad8 = 104,
NumPad9 = 105,
F1 = 112,
F2 = 113,
F3 = 114,
F4 = 115,
F5 = 116,
F6 = 117,
F7 = 118,
F8 = 119,
F9 = 120,
F10 = 121,
F11 = 122,
F12 = 123,
NumLock = 144,
ScrollLock = 145,
Semicolon = 186,
Equal = 187,
Comma = 188,
Minus = 189,
Dot = 190,
Slash = 191,
BackQuote = 192,
LeftBracket = 219,
BackSlash = 220,
RightBracket = 221,
Quote = 222,
}
}
【本文作者 张赐荣】
标签:C#,热键,VirtualKey,Windows,int,hotkeyId,ModifiedKeys,public From: https://www.cnblogs.com/netlog/p/17931935.html