作者: 张赐荣
.NET 类库本身没有封装注册全局快捷键的函数,想要实现注册全局热键,就需要使用Win32API。
在WinAPI中,注册和注销全局快捷键分别通过registerhotkey和unregisterhotkey函数实现。
注册快捷键后,还需要重写窗口过程函数。
以下代码封装了全局快捷键注册功能 (在 Winform 项目中测试通过)
=代码开始=using System;using System.Runtime.InteropServices;
namespace CRHotkey{ internal delegate IntPtr WNDProc(IntPtr hwnd, uint messageID, IntPtr WParam, IntPtr LParam); public delegate void HotkeyEventHandler(Object sender, HotkeyInfo ea);
public static class Hotkey { private const int GWL_WNDPROC = (-4); private const uint WM_HOTKEY = 0x0312;
private static readonly IntPtr HWND = IntPtr.Zero; private static readonly IntPtr DEFWndProc = IntPtr.Zero;
public static event HotkeyEventHandler HotkeyPressed;
[DllImport("user32.dll", EntryPoint = "RegisterHotKey")] private static extern bool API_RegisterHotKey(IntPtr hWnd, uint id, uint fsModifiers, uint vk); [DllImport("user32.dll", EntryPoint = "UnregisterHotKey")] private static extern bool API_UnregisterHotKey(IntPtr hWnd, uint id); [DllImport("user32.dll", EntryPoint = "CallWindowProc")] private static extern IntPtr API_CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll", EntryPoint = "SetWindowLong")] private static extern IntPtr API_SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
static Hotkey() { HWND = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle; DEFWndProc = API_SetWindowLong(HWND, GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(new WNDProc(UDFWndProc))); }
private static IntPtr UDFWndProc(IntPtr hwnd, uint msgID, IntPtr WParam, IntPtr LParam) { if (msgID == WM_HOTKEY) { byte[] bit32 = BitConverter.GetBytes(LParam.ToInt32()); uint hkid = Convert.ToUInt32(WParam.ToInt32()); uint mk = BitConverter.ToUInt16(bit32, 0); uint key = BitConverter.ToUInt16(bit32, 2); HotkeyInfo ki = new HotkeyInfo(hkid, mk, key); HotkeyPressed?.Invoke(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle, ki); } return (API_CallWindowProc(DEFWndProc, hwnd, msgID, WParam, LParam)); }
public static bool RegisterHotkey(uint hotkeyID, ModifierKeys mk, VirtualKey vk) { try { bool res = API_RegisterHotKey(HWND, hotkeyID, ((uint)mk), ((uint)vk)); return (res); } catch (Exception ex) { return (false); } }
public static bool UnregisterHotkey(uint hotkeyID) { try { bool res = API_UnregisterHotKey(HWND, hotkeyID); return (res); } catch (Exception ex) { return (false); } } }
public class HotkeyInfo : EventArgs { private uint _HotkeyID = 0; public uint HotkeyID { get => this._HotkeyID; } private ModifierKeys _ModifierKeys = ModifierKeys.None; public ModifierKeys ModifierKeys { get => this._ModifierKeys; } private VirtualKey _Key = VirtualKey.None; public VirtualKey Key { get => this._Key; }
public HotkeyInfo(uint hotkeyID, uint mk, uint vk) { this._HotkeyID = hotkeyID; this._ModifierKeys = (ModifierKeys)mk; this._Key = (VirtualKey)vk; } }
[Flags()] public enum ModifierKeys : uint { None = 0, Alt = 1, Ctrl = 2, Shift = 4, WinKey = 8, }
public enum VirtualKey : uint { None = 0, BackSpace = 8, Tab = 9, Clear = 12, Enter = 13, Pause = 19, CapsLock = 20, Escape = 27, Space = 32, PageUp = 33, PageDown = 34, End = 35, Home = 36, Left = 37, Up = 38, Right = 39, Down = 40, PrintScreen = 44, Insert = 45, Delete = 46, Help = 47, Key0 = 48, Key1 = 49, Key2 = 50, Key3 = 51, Key4 = 52, Key5 = 53, Key6 = 54, Key7 = 55, Key8 = 56, Key9 = 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, Application = 93, Sleep = 95, NumPad0 = 96, NumPad1 = 97, NumPad2 = 98, NumPad3 = 99, NumPad4 = 100, NumPad5 = 101, NumPad6 = 102, NumPad7 = 103, NumPad8 = 104, NumPad9 = 105, Multiply = 106, Add = 107, Separator = 108, Subtract = 109, Decimal = 110, Divide = 111, 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, Scroll = 145, Semicolon = 186, Equals = 187, Comma = 188, Minus = 189, Dot = 190, Slash = 191, BackQuote = 192, LeftBracket = 219, BackSlash = 220, RightBracket = 211, Quote = 222, }}
=代码结束=
这是关于c#实现全局快捷键函数的文章。
我希望它能帮助你学习。
推荐阅读 《在 WinForms 项目中使用全局快捷键》: https://chowdera.com/2022/02/202202191319103608.html
原创文章,作者:bd101bd101,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/273821.html