主要有下面三种方式访问键盘的消息:(1) WM_CHAR (2) WM_KEYDOWN 和WM_KEYUP (3) GetAsyncKeyState()。
当键盘上的"A”被按下的时候,会产生两种数据: (1) ASCII (2) Scan Code ,扫描码。其中,ASCII码会区分A和a两种不同的形式。 Scan code不会区别他们。首先,我们介绍WM_CHAR的消息。
可以查看MSDN中的描述, http://msdn.microsoft.com/en-us/library/ms646276(v=vs.85).aspx。其中在系统中
#define WM_CHAR 0x0102
WM_CHAR 的消息具有下列参数:
wParam
The character code of the key. (ASCII)
lParam
The repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag, as shown in the following table.
Bits | Meaning |
0-15 | The repeat count for the current message. The value is the number of times the keystroke is autorepeated as a result of the user holding down the key. If the keystroke is held long enough, multiple messages are sent. However, the repeat count is not cumulative. |
16-23 | The scan code. The value depends on the OEM. |
24 | Indicates whether the key is an extended key, such as the right-hand ALT and CTRL keys that appear on an enhanced 101- or 102-key keyboard. The value is 1 if it is an extended key; otherwise, it is 0. |
25-28 | Reserved; do not use. |
29 | The context code. The value is 1 if the ALT key is held down while the key is pressed; otherwise, the value is 0. |
30 | The previous key state. The value is 1 if the key is down before the message is sent, or it is 0 if the key is up. |
31 | The transition state. The value is 1 if the key is being released, or it is 0 if the key is being pressed. |
Return Value
An application should return zero if it processes this message.
下面是一个关于测试WM_CHAR的例子。按下键盘的按钮后,将在console中输出wParam和lParam.
// INCLUDES /// #define WIN32_LEAN_AND_MEAN // just say no to MFC #include// include all the windows headers #include // include useful macros #include // very important and include WINMM.LIB too! #include #include #include // DEFINES // defines for windows #define WINDOW_CLASS_NAME "WINCLASS1" // GLOBALS HWND main_window_handle = NULL; // globally track main window HINSTANCE hinstance_app = NULL; // globally track hinstance // FUNCTIONS // LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { // this is the main message handler of the system PAINTSTRUCT ps; // used in WM_PAINT HDC hdc; // handle to a device context char buffer[80]; // used to print strings // what is the message switch(msg) { case WM_CREATE: { // do initialization stuff here // return success return(0); } break; case WM_CHAR: { // get the character char ascii_code = wparam; int key_state = lparam; // get a graphics context hdc = GetDC(hwnd); // set the foreground color to green SetTextColor(hdc, RGB(0,255,0)); // set the background color to black SetBkColor(hdc, RGB(0,0,0)); // set the transparency mode to OPAQUE SetBkMode(hdc, OPAQUE); // print the ascii code and key state sprintf(buffer,"WM_CHAR: Character = %c ",ascii_code); TextOut(hdc, 0,0, buffer, strlen(buffer)); sprintf(buffer,"Key State = 0X%X ",key_state); TextOut(hdc, 0,16, buffer, strlen(buffer)); // release the dc back ReleaseDC(hwnd, hdc); } break; case WM_PAINT: { // simply validate the window hdc = BeginPaint(hwnd,&ps); // end painting EndPaint(hwnd,&ps); // return success return(0); } break; case WM_DESTROY: { // kill the application, this sends a WM_QUIT message PostQuitMessage(0); // return success return(0); } break; default:break; } // end switch // process any messages that we didn't take care of return (DefWindowProc(hwnd, msg, wparam, lparam)); } // end WinProc // WINMAIN int WINAPI WinMain( HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) { WNDCLASSEX winclass; // this will hold the class we create HWND hwnd; // generic window handle MSG msg; // generic message // first fill in the window class stucture winclass.cbSize = sizeof(WNDCLASSEX); winclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW; winclass.lpfnWndProc = WindowProc; winclass.cbClsExtra = 0; winclass.cbWndExtra = 0; winclass.hInstance = hinstance; winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); winclass.hCursor = LoadCursor(NULL, IDC_ARROW); winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); winclass.lpszMenuName = NULL; winclass.lpszClassName = WINDOW_CLASS_NAME; winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); // save hinstance in global hinstance_app = hinstance; // register the window class if (!RegisterClassEx(&winclass)) return(0); // create the window if (!(hwnd = CreateWindowEx(NULL, // extended style WINDOW_CLASS_NAME, // class "WM_CHAR Demo", // title WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0,0, // initial x,y 400,300, // initial width, height NULL, // handle to parent NULL, // handle to menu hinstance,// instance of this application NULL))) // extra creation parms return(0); // save main window handle main_window_handle = hwnd; // enter main event loop, but this time we use PeekMessage() // instead of GetMessage() to retrieve messages while(TRUE) { // test if there is a message in queue, if so get it if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { // test if this is a quit if (msg.message == WM_QUIT) break; // translate any accelerator keys TranslateMessage(&msg); // send the message to the window proc DispatchMessage(&msg); } // end if // main game processing goes here // Game_Main(); // or whatever your loop is called } // end while // return to Windows like this return(msg.wParam); } // end WinMain ///