子类化后编辑控件无法获得焦点或设置文本
Edit control cannot get focus or set text after subclassing
我创建了一个编辑框,它工作得很好,但是在我为它添加了自定义 WndProc 之后,文本 "my edit" 不可见,并且在单击时不会获得焦点。
HWND handle=CreateWindowExW(0,L"Edit",L"my edit",WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_CENTER | ES_MULTILINE | ES_AUTOVSCROLL,
0,0,200,200,window.handle,0,GetModuleHandle(NULL),0);
在此之前一切正常
在我设置此 window 程序后,编辑控件不再按预期工作
SetWindowLongPtr(handle,GWLP_WNDPROC,(LRESULT)staticWndProc);
LRESULT CALLBACK staticWndProc(HWND handle, UINT uMsg, WPARAM wParam, LPARAM lParam){
switch (uMsg){
case WM_LBUTTONDOWN:
std::wcout << handle << L" click\n"; //click event works
break;
default:
return DefWindowProcW(handle,uMsg,wParam,lParam);
}
return 0;
}
我是否必须手动处理某些事件或更改我的构造样式标志?
Sub-classing 涉及拦截 window 的消息,可能会处理其中的一些消息,并将您不处理的消息传递给 原始 window 程序.
您没有这样做 - 您正在将您不处理的所有内容传递给 DefWindowProc
。 DefWindowProc
没有任何编辑控件(或任何类型的控件)的特殊行为。因此,您已经有效地将编辑控件变成了通用 window.
现在不鼓励使用 SetWindowLongPtr
子 class 一个 window,但是如果您确实使用该方法,则调用 return 的值 SetWindowLongPtr
给你旧的 window 过程,你打算使用 CallWndProc
函数而不是 DefWindowProc
来调用它。
然而,subclass a window 的现代方法是使用 SetWindowSubclass
函数,它会为您处理调用原始过程 - 您需要做的就是调用DefSubclassProc
函数,如下所示:
LRESULT CALLBACK staticWndProc(HWND handle, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR, DWORD_PTR){
switch (uMsg){
case WM_LBUTTONDOWN:
std::wcout << handle << L" click\n"; //click event works
break;
case WM_NCDESTROY:
RemoveWindowSubclass(handle, staticWndProc, 0);
// fall through
default:
return DefSubclassProc(handle,uMsg,wParam,lParam);
}
return 0;
}
SetWindowSubclass(handle, staticWndProc, 0, 0);
请注意,上面显示的 subclass 函数会在收到 WM_NCDESTROY
时自行删除。
我创建了一个编辑框,它工作得很好,但是在我为它添加了自定义 WndProc 之后,文本 "my edit" 不可见,并且在单击时不会获得焦点。
HWND handle=CreateWindowExW(0,L"Edit",L"my edit",WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_CENTER | ES_MULTILINE | ES_AUTOVSCROLL,
0,0,200,200,window.handle,0,GetModuleHandle(NULL),0);
在此之前一切正常
在我设置此 window 程序后,编辑控件不再按预期工作
SetWindowLongPtr(handle,GWLP_WNDPROC,(LRESULT)staticWndProc);
LRESULT CALLBACK staticWndProc(HWND handle, UINT uMsg, WPARAM wParam, LPARAM lParam){
switch (uMsg){
case WM_LBUTTONDOWN:
std::wcout << handle << L" click\n"; //click event works
break;
default:
return DefWindowProcW(handle,uMsg,wParam,lParam);
}
return 0;
}
我是否必须手动处理某些事件或更改我的构造样式标志?
Sub-classing 涉及拦截 window 的消息,可能会处理其中的一些消息,并将您不处理的消息传递给 原始 window 程序.
您没有这样做 - 您正在将您不处理的所有内容传递给 DefWindowProc
。 DefWindowProc
没有任何编辑控件(或任何类型的控件)的特殊行为。因此,您已经有效地将编辑控件变成了通用 window.
现在不鼓励使用 SetWindowLongPtr
子 class 一个 window,但是如果您确实使用该方法,则调用 return 的值 SetWindowLongPtr
给你旧的 window 过程,你打算使用 CallWndProc
函数而不是 DefWindowProc
来调用它。
然而,subclass a window 的现代方法是使用 SetWindowSubclass
函数,它会为您处理调用原始过程 - 您需要做的就是调用DefSubclassProc
函数,如下所示:
LRESULT CALLBACK staticWndProc(HWND handle, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR, DWORD_PTR){
switch (uMsg){
case WM_LBUTTONDOWN:
std::wcout << handle << L" click\n"; //click event works
break;
case WM_NCDESTROY:
RemoveWindowSubclass(handle, staticWndProc, 0);
// fall through
default:
return DefSubclassProc(handle,uMsg,wParam,lParam);
}
return 0;
}
SetWindowSubclass(handle, staticWndProc, 0, 0);
请注意,上面显示的 subclass 函数会在收到 WM_NCDESTROY
时自行删除。