2

我参考这篇文章;

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
    }

我的问题是,api如何RegisterHotKey知道 , 1, 2,48Windows 键?因为 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;
4

3 回答 3

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分配keyControl,ShiftAlt清除了标志”

我不确定为什么 pinvoke 的贡献者选择使用常量;您可以轻松地使用适当的枚举:

[Flags]
public enum Modifiers
{
   None = 0,
   Alt = 1,
   Control = 2,
   // ...
}

我对类似问题的回答有更多关于标志如何工作的详细信息,以及更多示例。

于 2009-03-24T06:38:07.337 回答
1

1、2、4、8 用于表示单个位。1 是最低有效位将打开。添加 2 将打开第二个最低有效位等。因此,您可以独立设置多个标志。

1 = 0001
2 = 0010
4 = 0100
8 = 1000

因此,如果您想将 2 和 4 表示的变量设置为 true,您将使用 0110 = 6。

于 2009-03-24T06:42:01.210 回答
0

如果您想了解有关 RegisterHotKey API 的更多信息,请查看此处:

API 帮助

此外,下载 Platform SDK 以查看 WinUser.h 以获得 MOD_ALT、MOD_CONTROL 等的定义值。

于 2009-03-24T06:41:25.907 回答