编辑控件在子类化后无法获得焦点或设置文本

Edit control cannot get focus or set text after subclassing

本文关键字:焦点 置文本 控件 子类 编辑      更新时间:2023-10-16

我已经创建了一个编辑框,它工作得很好,但是在我为它添加了一个自定义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);

在此之前一切正常
在我设置了这个窗口过程之后,编辑控件不再像预期的那样工作了

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" clickn"; //click event works
            break;
        default:
            return DefWindowProcW(handle,uMsg,wParam,lParam);
    }
    return 0;  
}

我必须手动处理一些事件或改变我的建筑风格标志吗?

子类化涉及截取窗口的消息,可能处理其中的一些消息,并将不处理的消息传递给原始窗口过程

你没有这样做——你把所有你不处理的事情都传递给了DefWindowProcDefWindowProc没有任何编辑控件(或任何类型的控件)的专门行为。所以你已经有效地把一个编辑控件变成了一个通用的窗口。

现在不鼓励使用SetWindowLongPtr来子类化窗口,但是如果您确实使用该方法,调用SetWindowLongPtr的返回值会给您旧的窗口过程,并且您意味着使用CallWndProc函数而不是DefWindowProc来调用它。

然而,窗体子类化的现代方式是使用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" clickn"; //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);

注意,当接收到WM_NCDESTROY时,上面显示的子类函数将自己删除。