简体   繁体   English

改变window的WndProc

[英]Change WndProc of the window

I try to change standart WndProc function. I have this code:我尝试更改标准WndProc function。我有以下代码:

HWND btn = CreateWindowEx(WS_EX_TRANSPARENT | WS_EX_CLIENTEDGE, L"BUTTON", L"Window title", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON
    , 50, 50, 50, 50, (HWND)XApplicationMainWindow->window->_wnd, (HMENU)123,
    (HINSTANCE)GetWindowLongPtr(XApplicationMainWindow->window->_wnd, GWLP_HINSTANCE), NULL);

SetWindowLongPtrW(btn, GWLP_WNDPROC, (LONG_PTR)SubclassWindowProc);

I can use L"BUTTON" class name, but when I change WndProc function I'll have a problem.我可以使用L"BUTTON" class 名称,但是当我更改WndProc function 时,我会遇到问题。 在此处输入图像描述

On this picture, you can see the blank square and normal button.在这张图片上,您可以看到空白方块和普通按钮。 If I try to create new WNDCLASS or WNDCLASSEX , I'll have nothing... Why?如果我尝试创建新的WNDCLASS or WNDCLASSEX ,我将一无所有……为什么?

How can I change the standart WndProc function, if I use L"BUTTON" class name?如果我使用L"BUTTON" class 名称,如何更改标准WndProc function?

It's my second WndProc :这是我的第二个WndProc

LRESULT CALLBACK SubclassWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
    case WM_CREATE:
        break;
    case WM_COMMAND:

        //Event click
        switch (LOWORD(wParam))
        {
        case 123:
            OutputDebugStringA("Subclass click2");
            break;
        default:
            break;
        }

        break;
    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return 0;
}

DefWindowProc() is the wrong window procedure for your SubclassWindowProc() to be calling. DefWindowProc()是您要调用的SubclassWindowProc()的错误 window 过程。

You need to call the previous window procedure that you are replacing - the window procedure that handles all of the button's default behaviors (like drawing the button so it actually looks like a button, and responding to user input like a button, etc).您需要调用之前要替换的 window 过程 - 处理按钮所有默认行为的 window 过程(例如绘制按钮使其实际上看起来像按钮,并像按钮一样响应用户输入等)。 SetWindowLongPtr() returns a pointer to that procedure to you, but you are currently ignoring it. SetWindowLongPtr()向您返回指向该过程的指针,但您目前忽略了它。

See Subclassing Controls on MSDN for more details.有关详细信息,请参阅 MSDN 上的子类化控件

Try this instead:试试这个:

WNDPROC btnWndProc;

LRESULT CALLBACK SubclassWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_COMMAND:
            //Event click
            switch (LOWORD(wParam))
            {
                case 123:
                    OutputDebugStringA("Subclass click2");
                    break;
            }

            break;
    }

    return CallWindowProc(hWnd, btnWndProc, uMsg, wParam, lParam);
}

...

HWND btn = CreateWindowEx(...);

btnWndProc = (WNDPROC) SetWindowLongPtrW(btn, GWLP_WNDPROC, (LONG_PTR)SubclassWindowProc);

Alternatively, using SetWindowSubclass() , which issafer than using SetWindowsLongPtr() , eg:或者,使用SetWindowSubclass() ,这比使用SetWindowsLongPtr()更安全,例如:

LRESULT CALLBACK SubclassWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
    switch (uMsg) {
        case WM_NCDESTROY:
            RemoveWindowSubclass(hWnd, SubclassWindowProc, uIdSubclass);
            break;

        case WM_COMMAND:
            //Event click
            switch (LOWORD(wParam))
            {
                case 123:
                    OutputDebugStringA("Subclass click2");
                    break;
            }

            break;
    }

    return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}

...

HWND btn = CreateWindowEx(...);

SetWindowSubclass(btn, SubclassWindowProc, 1, 0);

Now, that being said, your subclass will never call OutputDebugStringA() , because it will never receive the WM_COMMAND message you are expecting.现在,话虽如此,您的子类永远不会调用OutputDebugStringA() ,因为它永远不会收到您期望的WM_COMMAND消息。 When a button is clicked, a WM_COMMAND message is not sent to the button itself.单击按钮时,不会向按钮本身发送WM_COMMAND消息。 The button posts a WM_COMMAND message to the button's parent window instead (in this case, to XApplicationMainWindow->window->_wnd ).该按钮改为将WM_COMMAND消息发送到按钮的父级 window (在本例中为XApplicationMainWindow->window->_wnd )。 So, you need to handle the WM_COMMAND message in the window procedure of the parent window , not in the window procedure of the button itself.因此,您需要在父 window的 window 过程中处理WM_COMMAND消息,而不是在按钮本身的 window 过程中。

Otherwise, if you still want to subclass the button itself, you will have to handle the WM_LBUTTON(DOWN|UP) and WM_KEY(DOWN|UP) / WM_CHAR messages that the button receives and then subsequently translates into a WM_COMMAND message for its parent window.否则,如果您仍想子类化按钮本身,则必须处理按钮接收到的WM_LBUTTON(DOWN|UP)WM_KEY(DOWN|UP) / WM_CHAR消息,然后将其转换为其父级 window 的WM_COMMAND消息.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM