我引用了这篇文章;
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 和菜单 (alt) 的按键代码会返回完全不同的按键值? RegisterHotKey
函数中到底发生了什么,它正在检查:
if ((key & Keys.Control) == Keys.Control)
modifiers = modifiers | WindowsShell.MOD_CONTROL;
它在这里做什么?
Keys k = key & ~Keys.Control & ~Keys.Shift & ~Keys.Alt;
最佳答案
MOD_ALT
、MOD_CONTROL
等与关联按键的键码没有任何关系。
您会看到一个 enum
类型,用于表示一组 flags 。这是一种特别紧凑的方式来表示表示事物组合的状态(例如同时按下修饰键、文件访问权限等)
当以这种方式使用enum
时,枚举类型变量的每一位都可以用来指示设置了特定的“标志”。
// 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 不必为每个修饰键采用单独的 bool 参数
- 可以扩展 API 以包含其他修饰键,而无需更改界面
按位&
和|
可用于确定值中设置了哪些标志,以及设置或取消设置值中的标志。
您询问的代码正是这样做的:
if ((key & Keys.Control) == Keys.Control)
modifiers = modifiers | WindowsShell.MOD_CONTROL
表示“如果该键设置了控制
位,则在修饰符
中设置控制位”
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,
// ...
}
My answer to a similar question有关标志如何工作的更多详细信息以及更多示例。
关于c# - 使用 RegisterHotKey api 调用时,为什么它接受 1、2、4 和 8 作为修饰符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/676341/