在C ++ WINAPI中对EDIT控件进行子类化时,窗口为空

时间:2013-03-23 20:50:50

标签: c++ winapi controls edit subclassing

我有一个EDIT控件,我尝试子类化,当我这样做时,整个窗口都是空的:

// Global variables
HINSTANCE hInst;
WNDPROC oldEditWndProc;
INT_PTR CALLBACK EditWndProc(HWND, UINT, WPARAM, LPARAM);

// Messages handler of the parent window
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    HDC hDC;
    HWND myedit;

    switch (message)
    {
    case WM_CREATE:
        // Create the EDIT control
        myedit= CreateWindowEx(
                               WS_EX_CLIENTEDGE|WS_EX_CONTROLPARENT, 
                               L"EDIT", 
                               L"",
                               WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_LEFT, 
                               20, 120, 
                               160, 20, 
                               hWnd, 
                               NULL, 
                               hInst, 
                               NULL
                              );
        oldEditWndProc = (WNDPROC)GetWindowLongPtr (myedit, GWLP_WNDPROC);
        // This is the line where problems begin
        SetWindowLongPtr (myedit, GWLP_WNDPROC, (LONG_PTR)EditWndProc);
        break;
    case WM_PAINT:
        hDC = BeginPaint(hWnd, &ps);
        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// EDIT control own handler
INT_PTR CALLBACK EditWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_GETDLGCODE:
            return DLGC_WANTTAB;
            break;
    }
    return (INT_PTR)FALSE;
}

在调用SetWindowLongPtr

时,我无法弄清楚为什么整个窗口都是空的

2 个答案:

答案 0 :(得分:3)

“空”意味着它没有在屏幕上显示?

如果是,那是因为当你子类化Window时,它的所有消息都将被发送到新的MessageProc,它没有所有的功能来正确显示它的defaultProc函数(例如WM_PAINT,甚至是一个按钮)点击)。

所以你需要这样的东西:

//store the old window proc somewhere
WNDPROC oldWindowProc = (WNDPROC)SetWindowLong(subWindowHandle, GWL_WNDPROC, long(NewMessageProc));

//and in the message proc
switch(uMsg)
{
    //your "case"s here
    default:
    {
        CallWindowProc(oldWindowProc, windowHandle, uMsg, wParam, lParam);
    }
}

这将调用正确的WM_PAINT和其他消息到messageProc,负责绘制和单击以及其他函数(子类窗口的DefWindowProc())。

或者您也可以在NewMessageProc中为所有子类窗口实现WM_PAINT,但是如果不调用他们的DefWindowProc,您需要为他们可能收到的每个事件做些事情(mousemove,鼠标点击,按钮点击,一切),所以使用他们原来的DefWindowProc更容易。

答案 1 :(得分:1)

在编辑窗口proc中,您需要调用一些适当的默认消息处理。

如原始窗口proc。

在代码的抽象级别,最简单的方法是使用SetWindowSubclass来进行子类化