C++ Can';t处理WM_键控消息
我试图使用以下wndproc和winmain处理WM_KEYDOWN消息,但当我按下一个键(即ascii值为24、25、26、27的箭头键)时,它不会处理C++ Can';t处理WM_键控消息,c++,windows,winapi,C++,Windows,Winapi,我试图使用以下wndproc和winmain处理WM_KEYDOWN消息,但当我按下一个键(即ascii值为24、25、26、27的箭头键)时,它不会处理 WndProc LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ /*TO CHECK uMsg message*/ char buff[256]; _itoa_s(uMsg, buff, 10); Set
WndProc
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
/*TO CHECK uMsg message*/
char buff[256];
_itoa_s(uMsg, buff, 10);
SetWindowText(hEdit, buff);
/**********************/
switch (uMsg)
case WM_CREATE:
hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "Edit", "", WS_CHILD | WS_VISIBLE |ES_AUTOVSCROLL | ES_MULTILINE | ES_WANTRETURN | WS_VSCROLL, 735, 5, 150, 100, hWnd, NULL, hInst, NULL);
HButton1 = CreateWindowEx(NULL, "BUTTON", "START", WS_CHILD | WS_VISIBLE | SS_CENTER, 2, 2, 80, 20, hWnd, (HMENU)IDC_BUTTON1, hInst, NULL);
HButton2 = CreateWindowEx(NULL, "BUTTON", "B", WS_CHILD | WS_VISIBLE | SS_CENTER, 82, 2, 80, 20, hWnd, (HMENU)IDC_BUTTON2, hInst, NULL);
HButton3 = CreateWindowEx(NULL, "BUTTON", "STOP", WS_CHILD | WS_VISIBLE | SS_CENTER, 162, 2, 80, 20, hWnd, (HMENU)IDC_BUTTON3, hInst, NULL);
Hmainbmp = CreateWindowEx(NULL, "STATIC", "", WS_CHILD | WS_VISIBLE | SS_BITMAP | WS_THICKFRAME, 1, 23, 600, 500, hWnd, NULL, hInst, NULL);
break;
case WM_KEYDOWN:
PRESSED_KEY = wParam;
break;
case WM_COMMAND:
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return(DefWindowProc(hWnd, uMsg, wParam, lParam));
return(0L);
}
WinMain
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){
MSG msg;
WNDCLASSEX wc;
HMENU MainMenu, FileMenu;
MainMenu = CreateMenu();
FileMenu = CreatePopupMenu();
AppendMenu(FileMenu, MF_STRING, IDC_OPEN, "Open");
AppendMenu(MainMenu, MF_POPUP, (UINT_PTR)FileMenu, "FILE");
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wc.lpszMenuName = lpszAppName;
wc.lpszClassName = lpszAppName;
wc.cbSize = sizeof(WNDCLASSEX);
wc.hIconSm = (HICON)LoadImage(hInstance, lpszAppName, IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
if (!RegisterClassEx(&wc)) return(FALSE);
hInst = hInstance;
hWnd = CreateWindowEx(0, lpszAppName, lpszTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 900, 600, NULL, MainMenu, hInstance, NULL);
if (!hWnd) return(FALSE);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
为什么下面的案例不起作用?我如何处理WM_键关闭
case WM_KEYDOWN:
PRESSED_KEY = wParam;
break;
更新
当我再次最小化和最大化窗口时,WM_KEYDOWN
已处理,但如果我单击任何按钮,它将不起作用。根据文档:
当按下非系统键时,以键盘焦点发布到窗口。非系统键是在未按下ALT键时按下的键
但是,窗口中还有其他按钮和编辑框。因此,当您按下其他按钮或单击编辑框时,焦点将集中在该窗口上。这将导致WndProc
功能无法处理WM_KEYDOWN
消息
您可以使用该功能设置键盘焦点窗口。然后您可以通过主窗口获取WM_KEYDOWN
消息,并通过编辑控件显示值
如以下代码所示:
case WM_KEYDOWN:
PRESSED_KEY = wParam;
_itoa_s(wParam, buff, 10);
SetWindowTextA(hEdit, buff);
break;
当然,如果您不想关注某个特定的窗口来获取键盘信息,我建议您使用该函数来获取全局键盘消息,而不要关注某个特定的窗口
编辑:
如果要处理所有WM_KEYDOWN
消息,可以使用SetWindowsHookEx
功能
您只需要修改代码的几个部分:
1.添加处理键盘的功能:
LRESULT __stdcall KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
char buff[256] = "";
PKBDLLHOOKSTRUCT key = (PKBDLLHOOKSTRUCT)lParam;
//a key was pressed
if (wParam == WM_KEYDOWN && nCode == HC_ACTION)
{
_itoa_s(key->vkCode, buff, 10);
SetWindowTextA(hEdit, buff);
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
2.在主功能中将钩子进程设置为键盘:
HHOOK _k_hook;
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR szCmdLine, _In_ int nCmdShow)
{
MSG msg;
WNDCLASSEX wc;
HMENU MainMenu, FileMenu;
_k_hook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, NULL, 0);
...
}
3.最后,不要忘记在程序结束后删除钩子进程:
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
HWND HButton1, HButton2, HButton3, Hmainbmp;
switch (uMsg)
{
...
case WM_DESTROY:
if (_k_hook)
UnhookWindowsHookEx(_k_hook);
PostQuitMessage(0);
break;
...
}
}
这样,您就不需要在
WndProc
中处理WM_KEYDOWN
的消息。按键信息在KeyboardProc
功能中处理,并且键的值显示在编辑控件中。可能是因为WM_KEYDOWN消息将发送到您创建的编辑控件。如果您想截获发送到编辑控件的键盘消息,必须使用一种称为的技术。另外请注意,箭头键的处理是特殊的,因为它们是操作系统为导航而保留的默认情况下,它们不会生成WM\u KEY…
消息。您必须通过处理返回DLGC\u WANTARROWS
标志的消息来显式地请求它。@john实际上,我想在按下键时更改全局变量(按下键)的值。键盘上的信息只会在有焦点的窗口中传递。用户可以通过单击窗口来更改具有焦点的窗口。因此,如果你真的想跟踪所有键盘使用情况,那么windows消息并不是最好的方法。也许你应该看看,尽管我没有这方面的经验。我希望WndProc
处理所有WM\u KEYDOWN
消息。你能分享你建议的例子吗?@不,我已经更新了我的答案,你可以参考。