1. WM_HOTKEY
This message is posted when the user presses a hot key registered by the RegisterHotKey function. The message is placed at the top of the message queue associated with the thread that registered the hot key.
WM_HOTKEY idHotKey = (int) wParam; fuModifiers = (UINT) LOWORD(lParam); uVirtKey = (UINT) HIWORD(lParam);
Value | Description |
---|---|
IDHOT_SNAPDESKTOP | The snap desktop hot key was pressed. |
IDHOT_SNAPWINDOW | The snap window hot key was pressed. |
Value | Description |
---|---|
MOD_ALT | Either ALT key was held down. |
MOD_CONTROL | Either CTRL key was held down. |
MOD_KEYUP | Both key up events and key down events generate a WM_HOTKEY message |
MOD_SHIFT | Either SHIFT key was held down. |
MOD_WIN | Either WINDOWS key was held down. These keys are labeled with the Microsoft Windows logo. |
Programming element | Description |
---|---|
WM_ACTIVATE | This message is sent when a window is being activated or deactivated. |
WM_CHAR | This message is posted to the window with the keyboard focus when a WM_KEYDOWN message is translated by the TranslateMessage function. |
WM_HOTKEY | This message is posted when the user presses a hot key registered by the RegisterHotKey function. |
WM_INITMENUPOPUP | This message is sent when a pop-up menu is about to become active. |
WM_KEYDOWN | This message is posted to the window with the keyboard focus when a nonsystem key is pressed. |
WM_KEYUP | This message is posted to the window with the keyboard focus when a nonsystem key is released. |
WM_KILLFOCUS | This message is sent to a window immediately before it loses the keyboard focus. |
WM_MENUCHAR | This message is sent when a menu is active and the user presses a key that does not correspond to any mnemonic or accelerator key. |
WM_SETFOCUS | This message is sent to a window after it has gained the keyboard focus. |
WM_SYSCHAR | This message is posted to the window with the keyboard focus when a WM_SYSKEYDOWN message is translated by the TranslateMessage function. |
WM_SYSCOMMAND | This message is sent to a window when the user chooses a command from the window menu, formerly known as the system or control menu, or when the user chooses the maximize button or the minimize button. |
WM_SYSDEADCHAR | This message is posted to the window with the keyboard focus when a WM_SYSKEYDOWN message is translated by the TranslateMessage function. |
WM_SYSKEYDOWN | This message is posted to the window with the keyboard focus when the user holds down the ALT key and then presses another key. |
WM_SYSKEYUP | This message is posted to the window with the keyboard focus when the user releases a key that was pressed while the ALT key was held down. |
3. RegisterHotKey
This function defines a system-wide hot key.
BOOL RegisterHotKey( HWND hWnd, int id, UINT fsModifiers, UINT vk );
Value | Description |
---|---|
MOD_ALT | Either ALT key must be held down. |
MOD_CONTROL | Either CTRL key must be held down. |
MOD_KEYUP | Both key up events and key down events generate a WM_HOTKEY message. |
MOD_SHIFT | Either SHIFT key must be held down. |
MOD_WIN | Either WINDOWS key was held down. These keys are labeled with the Microsoft Windows logo. |
Nonzero indicates success. Zero indicates failure.
When a key is pressed, the system looks for a match against all hot keys. Upon finding a match, the system posts the WM_HOTKEY message to the message queue of the thread that registered the hot key. This message is posted to the beginning of the queue so it is removed by the next iteration of the message loop.
RegisterHotKey can be used to register hot keys across threads.
RegisterHotKey fails if the keystrokes specified for the hot key have already been registered by another hot key.
If the window identified by the hWnd parameter already registered a hot key with the same identifier as that specified by the id parameter, the new values for the fsModifiers and vk parameters replace the previously specified values for these parameters.
4. Virtual-Key Codes
Symbolic constant | Hexadecimal value | Mouse or keyboard equivalent |
---|---|---|
VK_LBUTTON | 01 | Left mouse button |
VK_RBUTTON | 02 | Right mouse button |
VK_CANCEL | 03 | Control-break processing |
VK_MBUTTON | 04 | Middle mouse button on a three-button mouse |
0507 | Undefined | |
VK_BACK | 08 | BACKSPACE key |
VK_TAB | 09 | TAB key |
0A0B | Undefined | |
VK_CLEAR | 0C | CLEAR key |
VK_RETURN | 0D | ENTER key |
0E0F | Undefined | |
VK_SHIFT | 10 | SHIFT key |
VK_CONTROL | 11 | CTRL key |
VK_MENU | 12 | ALT key |
VK_PAUSE | 13 | PAUSE key |
VK_CAPITAL | 14 | CAPS LOCK key |
1519 | Reserved for Kanji systems | |
1A | Undefined | |
VK_ESCAPE | 1B | ESC key |
1C1F | Reserved for Kanji systems | |
VK_SPACE | 20 | SPACEBAR |
VK_PRIOR | 21 | PAGE UP key |
VK_NEXT | 22 | PAGE DOWN key |
VK_END | 23 | END key |
VK_HOME | 24 | HOME key |
VK_LEFT | 25 | LEFT ARROW key |
VK_UP | 26 | UP ARROW key |
VK_RIGHT | 27 | RIGHT ARROW key |
VK_DOWN | 28 | DOWN ARROW key |
VK_SELECT | 29 | SELECT key |
2A | Specific to original equipment manufacturer | |
VK_EXECUTE | 2B | EXECUTE key |
VK_SNAPSHOT | 2C | PRINT SCREEN key |
VK_INSERT | 2D | INS key |
VK_DELETE | 2E | DEL key |
VK_HELP | 2F | HELP key |
3A40 | Undefined | |
VK_LWIN | 5B | Left Windows key on a Microsoft Natural Keyboard |
VK_RWIN | 5C | Right Windows key on a Microsoft Natural Keyboard |
VK_APPS | 5D | Applications key on a Microsoft Natural Keyboard |
5E5F | Undefined | |
VK_NUMPAD0 | 60 | Numeric keypad 0 key |
VK_NUMPAD1 | 61 | Numeric keypad 1 key |
VK_NUMPAD2 | 62 | Numeric keypad 2 key |
VK_NUMPAD3 | 63 | Numeric keypad 3 key |
VK_NUMPAD4 | 64 | Numeric keypad 4 key |
VK_NUMPAD5 | 65 | Numeric keypad 5 key |
VK_NUMPAD6 | 66 | Numeric keypad 6 key |
VK_NUMPAD7 | 67 | Numeric keypad 7 key |
VK_NUMPAD8 | 68 | Numeric keypad 8 key |
VK_NUMPAD9 | 69 | Numeric keypad 9 key |
VK_MULTIPLY | 6A | Multiply key |
VK_ADD | 6B | Add key |
VK_SEPARATOR | 6C | Separator key |
VK_SUBTRACT | 6D | Subtract key |
VK_DECIMAL | 6E | Decimal key |
VK_DIVIDE | 6F | Divide key |
VK_F1 | 70 | F1 key |
VK_F2 | 71 | F2 key |
VK_F3 | 72 | F3 key |
VK_F4 | 73 | F4 key |
VK_F5 | 74 | F5 key |
VK_F6 | 75 | F6 key |
VK_F7 | 76 | F7 key |
VK_F8 | 77 | F8 key |
VK_F9 | 78 | F9 key |
VK_F10 | 79 | F10 key |
VK_F11 | 7A | F11 key |
VK_F12 | 7B | F12 key |
VK_F13 | 7C | F13 key |
VK_F14 | 7D | F14 key |
VK_F15 | 7E | F15 key |
VK_F16 | 7F | F16 key |
VK_F17 | 80H | F17 key |
VK_F18 | 81H | F18 key |
VK_F19 | 82H | F19 key |
VK_F20 | 83H | F20 key |
VK_F21 | 84H | F21 key |
VK_F22 | 85H | F22 key (PPC only) Key used to lock device. |
VK_F23 | 86H | F23 key |
VK_F24 | 87H | F24 key |
888F | Unassigned | |
VK_NUMLOCK | 90 | NUM LOCK key |
VK_SCROLL | 91 | SCROLL LOCK key |
VK_LSHIFT | 0xA0 | Left SHIFT |
VK_RSHIFT | 0xA1 | Right SHIFT |
VK_LCONTROL | 0xA2 | Left CTRL |
VK_RCONTROL | 0xA3 | Right CTRL |
VK_LMENU | 0xA4 | Left ALT |
VK_RMENU | 0xA5 | Right ALT |
BA-C0 | Specific to original equipment manufacturer; reserved. See following tables. | |
C1-DA | Unassigned | |
DB-E2 | Specific to original equipment manufacturer; reserved. See following tables. | |
E3 – E4 | Specific to original equipment manufacturer | |
E5 | Unassigned | |
E6 | Specific to original equipment manufacturer | |
VK_PACKET | E7 | Used to pass Unicode characters as if they were keystrokes. If VK_PACKET is used with SendInput, then the Unicode character to be delivered should be placed into the lower 16 bits of the scan code. If a keyboard message is removed from the message queue and the virtual key is VK_PACKET, then the Unicode character will be the upper 16 bits of the lparam. |
E8 | Unassigned | |
E9-F5 | Specific to original equipment manufacturer | |
VK_ATTN | F6 | ATTN key |
VK_CRSEL | F7 | CRSEL key |
VK_EXSEL | F8 | EXSEL key |
VK_EREOF | F9 | Erase EOF key |
VK_PLAY | FA | PLAY key |
VK_ZOOM | FB | ZOOM key |
VK_NONAME | FC | Reserved for future use |
VK_PA1 | FD | PA1 key |
VK_OEM_CLEAR | FE | CLEAR key |
VK_KEYLOCK | F22 | Key used to lock device |
Original equipment manufacturers should make special note of the VK key ranges reserved for specific original equipment manufacturer use: 2A, DBE4, E6, and E9F5.
In addition to the VK key assignments in the previous table, Microsoft has assigned the following specific original equipment manufacturer VK keys.
Symbolic constant | Hexadecimal value | Mouse or keyboard equivalent |
---|---|---|
VK_OEM_SCROLL | 0x91 | None |
VK_OEM_1 | 0xBA | ";:" for US |
VK_OEM_PLUS | 0xBB | "+" any country/region |
VK_OEM_COMMA | 0xBC | "," any country/region |
VK_OEM_MINUS | 0xBD | "-" any country/region |
VK_OEM_PERIOD | 0xBE | "." any country/region |
VK_OEM_2 | 0xBF | "/?" for US |
VK_OEM_3 | 0xC0 | "`~" for US |
VK_OEM_4 | 0xDB | "[{" for US |
VK_OEM_5 | 0xDC | "\|" for US |
VK_OEM_6 | 0xDD | "]}" for US |
VK_OEM_7 | 0xDE | "'"" for US |
VK_OEM_8 | 0xDF | None |
VK_OEM_AX | 0xE1 | AX key on Japanese AX keyboard |
VK_OEM_102 | 0xE2 | "<>" or "\|" on RT 102-key keyboard |
5. 如何POST一个WM_HOTKEY消息?
首先从上面MSDN中关于WM_HOTKEY的内容可以看到,如何填入wParam、lParam参数.
(转来一段)运用PostMessage(HWND_BROADCAST, WM_HOTKEY, 0, MAKELONG(MOD_ALT | MOD_CONTROL, VK_DELETE));来发送虚拟键盘,但是在winNT以后的系统里我们还有很多事情要做,比如:OpenDesktop()、OpenInputDesktop()、GetThreadDesktop()、SetThreadDesktop()、CloseDesktop()、GetUserObjectInformation()
代码如下:(直接PostMessage是没有起作用,下面这个做法,VK_DELETE换成其他键值也同样效果,为啥?)
#include "windows.h"
BOOL simulateAltControlDel();
void main()
{
simulateAltControlDel();
}
BOOL simulateAltControlDel()
{
HDESK hdeskCurrent;
HDESK hdesk;
HWINSTA hwinstaCurrent;
HWINSTA hwinsta;
//
// Save the current Window station
//
hwinstaCurrent = GetProcessWindowStation();
if (hwinstaCurrent == NULL)
return FALSE;
//
// Save the current desktop
//
hdeskCurrent = GetThreadDesktop(GetCurrentThreadId());
if (hdeskCurrent == NULL)
return FALSE;
//
// Obtain a handle to WinSta0 - service must be running
// in the LocalSystem account
//
hwinsta = OpenWindowStation("winsta0", FALSE,
WINSTA_ACCESSCLIPBOARD |
WINSTA_ACCESSGLOBALATOMS |
WINSTA_CREATEDESKTOP |
WINSTA_ENUMDESKTOPS |
WINSTA_ENUMERATE |
WINSTA_EXITWINDOWS |
WINSTA_READATTRIBUTES |
WINSTA_READSCREEN |
WINSTA_WRITEATTRIBUTES);
if (hwinsta == NULL)
return FALSE;
//
// Set the windowstation to be winsta0
//
if (!SetProcessWindowStation(hwinsta))
return FALSE;
//
// Get the default desktop on winsta0
//
hdesk = OpenDesktop("Winlogon", 0, FALSE,
DESKTOP_CREATEMENU |
DESKTOP_CREATEWINDOW |
DESKTOP_ENUMERATE |
DESKTOP_HOOKCONTROL |
DESKTOP_JOURNALPLAYBACK |
DESKTOP_JOURNALRECORD |
DESKTOP_READOBJECTS |
DESKTOP_SWITCHDESKTOP |
DESKTOP_WRITEOBJECTS);
if (hdesk == NULL)
return FALSE;
//
// Set the desktop to be "default"
//
if (!SetThreadDesktop(hdesk))
return FALSE;
PostMessage(HWND_BROADCAST,WM_HOTKEY,0,MAKELPARAM(MOD_ALT|MOD_CONTROL,VK_DELETE));
//
// Reset the Window station and desktop
//
if (!SetProcessWindowStation(hwinstaCurrent))
return FALSE;
if (!SetThreadDesktop(hdeskCurrent))
return FALSE;
//
// Close the windowstation and desktop handles
//
if (!CloseWindowStation(hwinsta))
return FALSE;
if (!CloseDesktop(hdesk))
return FALSE;
return TRUE;
}
偶一开始试验了发现不成功,后来冰河大哥告诉我说OpenDesktop("Winlogon", ......)本身需要LocalSystem权限,
他说的注册为服务应该是这个:Running CMD.EXE as Local System
原理清楚了,不过我还是到Google了搜了下,找到了两篇相关文章。
一篇就叫《利用服务创建SYSTEM权限CMD》,说不定就和这个小工具有关系。
另外一篇是一个国外的一个大牛在MSDN的Blog上的,就叫《Running CMD.EXE as Local System 》。
这个人说了一种直接用sc命令创建服务来运行SYSTEM权限的CMD的方法,测试了下,果然很好用。
我把它写成如下一个简单的批处理,同样可以得到SYSTEM权限的CMD:
sc Create SuperCMD binPath= "cmd /K start" type= own type= interact
sc start SuperCMD