窗口进程/回调函数可以是类的成员函数吗?



例如,当您在窗口中的屏幕上创建一个窗口时,您将创建一个回调函数来接收来自窗口的消息

 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)

你能使这个函数成为类的成员函数吗?如果是这样,我该怎么做?我希望回调函数成为类成员的原因是可以访问某些变量,同时仍然封装变量。例如,我保存窗口的宽度和高度,因此如果要更改它们,我可以直接在回调函数中更改它们。

如果没有,您对我如何解决这个问题,让回调函数访问封装变量有什么建议吗?

就像注释建议static成员函数和SetWindowLongPtr的组合一样,可以使用来实现您想要做的事情。

下面是将静态WindowProc定义为成员函数的示例类声明。

class MyClass
{
public:
    void MainThreadProc ();
private:
    static LRESULT CALLBACK WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    LRESULT _WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};

MainThreadProc 方法将创建窗口。确保将this传递给CreateWindowEx因为这是您访问班级成员的方式。

void MyClass::MainThreadProc()
{
    MSG msg;    
    HINSTANCE hinstance = GetModuleHandle (NULL);    
    WNDCLASSEX wcx = {0};
    HWND hwnd = NULL;
    wcx.cbSize = sizeof wcx;
    wcx.hInstance = hinstance;
    wcx.hCursor = LoadCursor (NULL, IDC_NO);
    wcx.style = CS_HREDRAW | CS_VREDRAW;
    wcx.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
    wcx.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wcx.lpfnWndProc = WindowProc;
    wcx.lpszClassName = L"MyWindowClass";
    RegisterClassEx (&wcx);
    hwnd = CreateWindowEx ( WS_EX_APPWINDOW,
                            L"MyWindowClass",
                            L"MyWindow",
                            WS_OVERLAPPEDWINDOW,
                            CW_USEDEFAULT,
                            CW_USEDEFAULT,
                            CW_USEDEFAULT,
                            CW_USEDEFAULT,
                            NULL,
                            NULL,
                            hinstance,
                            this);
    ShowWindow (hwnd, SW_SHOWDEFAULT);    
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

WindowProc中,您将使用 SetWindowLongPtr 存储this对象以备将来使用。

LRESULT MyClass::WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    if (WM_NCCREATE == uMsg)
    {
        SetWindowLongPtr (hwnd, GWLP_USERDATA, (LONG_PTR) ((CREATESTRUCT*) lParam)->lpCreateParams);
        return TRUE;
    }
    return ((MyClass*) GetWindowLongPtr (hwnd, GWLP_USERDATA))->_WindowProc (hwnd, uMsg, wParam, lParam);
}

为了完整起见,这里是用于处理窗口消息的最后一个成员函数,此时您将可以访问所有类成员。

LRESULT MyClass::_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {   
    case WM_DESTROY:
        PostQuitMessage (S_OK);
        break;
    default:
        return DefWindowProc (hwnd, uMsg, wParam, lParam);
    }
    return 0;
}

最新更新