我参考这篇文章;
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
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,如何RegisterHotKeyAPI知道1,2,4,8是Windows键?因为ctrl,shift和menu(alt)的键代码会为键提供完全不同的值?RegisterHotKey在它正在检查的函数中究竟发生了什么:
if ((key & Keys.Control) == Keys.Control)
modifiers = modifiers | WindowsShell.MOD_CONTROL;
Run Code Online (Sandbox Code Playgroud)
它在这做什么?
Keys k = key & ~Keys.Control & ~Keys.Shift & ~Keys.Alt;
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
这有两个好处:
按位&s和|s可用于确定在值中设置哪些标志,以及在值中设置或取消设置标志.
您询问的代码就是这样做的:
if ((key & Keys.Control) == Keys.Control)
modifiers = modifiers | WindowsShell.MOD_CONTROL
Run Code Online (Sandbox Code Playgroud)
正在说"如果密钥Control设置了位,则将控制位设置为modifiers"
Keys k = key & ~Keys.Control & ~Keys.Shift & ~Keys.Alt;
Run Code Online (Sandbox Code Playgroud)
是说" k被分配key了Control,Shift并且Alt标志清除了"
我不确定为什么pinvoke的贡献者选择使用常量; 您可以轻松使用适当的枚举:
[Flags]
public enum Modifiers
{
None = 0,
Alt = 1,
Control = 2,
// ...
}
Run Code Online (Sandbox Code Playgroud)
我对类似问题的回答有关于标志如何工作的更多细节,以及更多示例.