我参考这篇文章;
http://www.pinvoke.net/default.aspx/user32/RegisterHotKey.html
#region fields public static int MOD_ALT = 0x1; public static int MOD_CONTROL = 0x2; public static int MOD_SHIFT = 0x4; public static int MOD_WIN = 0x8; public static int WM_HOTKEY = 0x312; #endregion [DllImport("user32.dll")] private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc); [DllImport("user32.dll")] private static extern bool UnregisterHotKey(IntPtr hWnd, int id); private static int keyId; public static void RegisterHotKey(Form f, Keys key) { int modifiers = 0; if ((key & Keys.Alt) == Keys.Alt) modifiers = modifiers | WindowsShell.MOD_ALT; if ((key & Keys.Control) == Keys.Control) modifiers = modifiers | WindowsShell.MOD_CONTROL; if ((key & Keys.Shift) == Keys.Shift) modifiers = modifiers | WindowsShell.MOD_SHIFT; Keys k = key & ~Keys.Control & ~Keys.Shift & ~Keys.Alt; Func ff = delegate() { keyId = f.GetHashCode(); // this should be a key unique ID, modify this if you want more than one hotkey RegisterHotKey((IntPtr)f.Handle, keyId, modifiers, (int)k); }; f.Invoke(ff); // this should be checked if we really need it (InvokeRequired), but it's faster this way }
我的问题是,如何RegisterHotKey
API知道1
,2
,4
,8
是Windows键?因为ctrl,shift和menu(alt)的键代码会为键提供完全不同的值?RegisterHotKey
在它正在检查的函数中究竟发生了什么:
if ((key & Keys.Control) == Keys.Control) modifiers = modifiers | WindowsShell.MOD_CONTROL;
它在这做什么?
Keys k = key & ~Keys.Control & ~Keys.Shift & ~Keys.Alt;
Daniel LeChe.. 5
MOD_ALT
,MOD_CONTROL
等,与关联密钥的密钥代码没有任何关系.
您将看到enum
用于表示一组标志的类型.这是一种表示状态组合的状态的特别紧凑的方式(如同时按下修改键,文件访问权限等)
当enum
以这种方式使用s时,枚举类型的变量的每个位可用于指示设置了特定的"标志".
// Note that powers of 2 are used; each value has only a single bit set public static int MOD_ALT = 0x1; // If bit 0 is set, Alt is pressed public static int MOD_CONTROL = 0x2; // If bit 1 is set, Ctrl is pressed public static int MOD_SHIFT = 0x4; // If bit 2 is set, Shift is pressed public static int MOD_WIN = 0x8; // If bit 3 is set, Win is pressed // If we wanted to represent a combination of keys: int altAndControl = MOD_ALT | MOD_CONTROL; // == 3 int controlAndShift = MOD_CONTROL | MOD_SHIFT; // == 6
这有两个好处:
API不必为每个修饰键采用单独的布尔参数
可以扩展API以包含其他修饰键而无需更改界面
按位&
s和|
s可用于确定在值中设置哪些标志,以及在值中设置或取消设置标志.
您询问的代码就是这样做的:
if ((key & Keys.Control) == Keys.Control) modifiers = modifiers | WindowsShell.MOD_CONTROL
正在说"如果密钥Control
设置了位,则将控制位设置为modifiers
"
Keys k = key & ~Keys.Control & ~Keys.Shift & ~Keys.Alt;
是说" k
被分配key
了Control
,Shift
并且Alt
标志清除了"
我不确定为什么pinvoke的贡献者选择使用常量; 您可以轻松使用适当的枚举:
[Flags] public enum Modifiers { None = 0, Alt = 1, Control = 2, // ... }
我对类似问题的回答有关于标志如何工作的更多细节,以及更多示例.
MOD_ALT
,MOD_CONTROL
等,与关联密钥的密钥代码没有任何关系.
您将看到enum
用于表示一组标志的类型.这是一种表示状态组合的状态的特别紧凑的方式(如同时按下修改键,文件访问权限等)
当enum
以这种方式使用s时,枚举类型的变量的每个位可用于指示设置了特定的"标志".
// Note that powers of 2 are used; each value has only a single bit set public static int MOD_ALT = 0x1; // If bit 0 is set, Alt is pressed public static int MOD_CONTROL = 0x2; // If bit 1 is set, Ctrl is pressed public static int MOD_SHIFT = 0x4; // If bit 2 is set, Shift is pressed public static int MOD_WIN = 0x8; // If bit 3 is set, Win is pressed // If we wanted to represent a combination of keys: int altAndControl = MOD_ALT | MOD_CONTROL; // == 3 int controlAndShift = MOD_CONTROL | MOD_SHIFT; // == 6
这有两个好处:
API不必为每个修饰键采用单独的布尔参数
可以扩展API以包含其他修饰键而无需更改界面
按位&
s和|
s可用于确定在值中设置哪些标志,以及在值中设置或取消设置标志.
您询问的代码就是这样做的:
if ((key & Keys.Control) == Keys.Control) modifiers = modifiers | WindowsShell.MOD_CONTROL
正在说"如果密钥Control
设置了位,则将控制位设置为modifiers
"
Keys k = key & ~Keys.Control & ~Keys.Shift & ~Keys.Alt;
是说" k
被分配key
了Control
,Shift
并且Alt
标志清除了"
我不确定为什么pinvoke的贡献者选择使用常量; 您可以轻松使用适当的枚举:
[Flags] public enum Modifiers { None = 0, Alt = 1, Control = 2, // ... }
我对类似问题的回答有关于标志如何工作的更多细节,以及更多示例.