【发布时间】:2021-07-23 11:04:54
【问题描述】:
对于像按钮、编辑等标准控件,我可以将其子类化,但是对于子窗口(我用作容器)如何完成?我知道WM_KEYDOWN 已发送到父窗口,但我无法直接从相应的子窗口获取它。我试过子类化它(不确定这是否有意义,因为它是一个窗口并且在WNDCLASSW.lpfnWndProc 成员中已经有自己的窗口过程)但是这个子过程无论如何都没有收到WM_KEYDOWN 消息。我可以通过使用GetCursorPos() 和WindowFromPoint() 从光标位置(我也需要考虑键盘焦点)获取控件的hwnd,如下所示,但我觉得它很hacky。这样做的正确方法是什么?
目前看起来是这样的:
case WM_KEYUP:
case WM_KEYDOWN:
{
POINT p;
if(GetCursorPos(&p))
{
HWND control = WindowFromPoint(p);
if(control)
{
// just testing it
int len = GetWindowTextLength(control);
wchar_t buffer[len + 1];
GetWindowText(control, buffer, sizeof(buffer));
MessageBox(NULL, buffer, L"", MB_OK);
}
}
}
break;
窗口如下所示:
目标是在用户键入内容的相应窗口上捕获 WM_KEYDOWN,然后调用一个函数来处理此事件,例如window1_onKeyDown()、window2_onKeyDown() 等。
这里是完整的代码:
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "Comctl32.lib")
#pragma comment(lib, "Gdi32.lib")
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WndProc1(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK WndProc2(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void createWindow1(HWND);
void createWindow2(HWND);
HBRUSH hBrush1, hBrush2;
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PWSTR lpCmdLine, int nCmdShow) {
MSG msg;
WNDCLASSW wc = {0};
wc.lpszClassName = L"my window";
wc.hInstance = hInstance;
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wc.lpfnWndProc = WndProc;
wc.hCursor = LoadCursor(0, IDC_ARROW);
hBrush1 = CreateSolidBrush(RGB(173, 164, 237));
hBrush2 = CreateSolidBrush(RGB(171, 171, 171));
RegisterClassW(&wc);
CreateWindowW(wc.lpszClassName, L"window",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
100, 100, 330, 270, NULL, 0, hInstance, 0);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
DeleteObject(hBrush1);
DeleteObject(hBrush2);
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam) {
switch(msg)
{
case WM_CREATE:
createWindow1(hwnd);
createWindow2(hwnd);
break;
case WM_KEYUP:
case WM_KEYDOWN:
{
POINT p;
if(GetCursorPos(&p))
{
HWND control = WindowFromPoint(p);
if(control)
{
int len = GetWindowTextLength(control);
wchar_t buffer[len + 1];
GetWindowText(control, buffer, sizeof(buffer));
MessageBox(NULL, buffer, L"", MB_OK);
}
}
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
void createWindow1(HWND hOwner)
{
WNDCLASSW wc = {0};
wc.lpszClassName = L"window2";
wc.hInstance = NULL;
wc.hbrBackground = hBrush1;
wc.lpfnWndProc = WndProc1;
wc.hCursor = LoadCursor(0, IDC_ARROW);
RegisterClassW(&wc);
CreateWindowW(wc.lpszClassName, L"window2",
WS_VISIBLE | WS_TABSTOP | WS_CHILD | WS_EX_CONTROLPARENT,
5, 5, 200, 100,
hOwner, 0, NULL, 0);
}
void createWindow2(HWND hOwner)
{
WNDCLASSW wc = {0};
wc.lpszClassName = L"window3";
wc.hInstance = NULL;
wc.hbrBackground = hBrush2;
wc.lpfnWndProc = WndProc2;
wc.hCursor = LoadCursor(0, IDC_ARROW);
RegisterClassW(&wc);
CreateWindowW(wc.lpszClassName, L"window3",
WS_VISIBLE | WS_TABSTOP | WS_CHILD,
5, 120, 200, 100,
hOwner, 0, NULL, 0);
}
LRESULT CALLBACK WndProc1(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
CreateWindow(L"Button", L"Button A",
WS_VISIBLE | WS_TABSTOP | WS_CHILD,
5, 5, 80, 25,
hwnd, 0, NULL, 0);
break;
case WM_KEYUP:
case WM_KEYDOWN:
MessageBox(NULL, L"hello from proc1", L"", MB_OK);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
LRESULT CALLBACK WndProc2(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
CreateWindow(L"Button", L"Button ",
WS_VISIBLE | WS_TABSTOP | WS_CHILD,
5, 5, 80, 25,
hwnd, 0, NULL, 0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
【问题讨论】:
标签: winapi keyboard focus onkeydown