I reference to this post;
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 }
My question is, how does RegisterHotKey api know that 1, 2, 4, 8 are windows keys? Because the key codes for ctrl, shift, and menu (alt) give back totally different values for the keys? And what exactly is going on in the RegisterHotKey function where it’s checking for:
if ((key & Keys.Control) == Keys.Control) modifiers = modifiers | WindowsShell.MOD_CONTROL;
and what is it doing here?
Keys k = key & ~Keys.Control & ~Keys.Shift & ~Keys.Alt;
MOD_ALT,MOD_CONTROL, etc don’t have any relationship to the keycodes of the associated keys.You’re seeing an
enumtype used to represent a set of flags. This is a particularly compact way of representing states that represent combinations of things (like modifier keys being simultaneously pressed, file access permissions, etc)When
enums are used this way, each bit of a variable of the enumeration type can be used to indicate that a particular ‘flag’ is set.This has two advantages:
Bitwise
&s and|s can be used to determine which flags are set in a value, and to set or unset a flag in a value.The code you’ve asked about does exactly this:
is saying ‘If the key has the
Controlbit set, then set the control bit inmodifiers‘is saying ‘
kis assignedkeywith theControl,ShiftandAltflags cleared’I’m not sure why the contributors to pinvoke chose to use constants; you can just as easily use a proper enum:
My answer to a similar question has some more details on how flags work, and more examples.