无法处理WM_KEYDOWN消息

Can't handle WM_KEYDOWN message

本文关键字:KEYDOWN 消息 WM 处理      更新时间:2024-09-29

我正试图使用以下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);
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_KEYDOWN?

case WM_KEYDOWN:
PRESSED_KEY = wParam;
break;

更新

当我再次最小化和最大化窗口时,WM_KEYDOWN进行了处理,但如果我单击任何按钮,它都不起作用。

根据WM_KEYDOWN文档:

当按下非系统键时,以键盘焦点张贴到窗口。非系统键是指未按下ALT键时按下的键。

但是,您的窗口中还有其他按钮和编辑框。因此,当您按下其他按钮或单击编辑框时,焦点将集中在该窗口上。这将导致WndProc功能无法处理WM_KEYDOWN消息。

您可以使用SetFocus功能来设置键盘焦点窗口。然后,您可以通过主窗口获得WM_KEYDOWN消息,并通过Edit控件显示值。

类似以下代码:

case WM_KEYDOWN:
PRESSED_KEY = wParam;
_itoa_s(wParam, buff, 10);
SetWindowTextA(hEdit, buff);
break;

当然,如果您不想专注于特定窗口来获取键盘信息,我建议您使用SetWindowsHookEx函数来获取全局键盘消息,而不必专注于特定的窗口。

编辑:

如果要处理所有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功能中进行处理,按键值显示在Edit控件中。