Windows proc / callback函数可以成为类的成员函数吗?

时间:2015-01-28 15:10:54

标签: c++ windows callback

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

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

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

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

1 个答案:

答案 0 :(得分:3)

就像评论提示的那样,可以使用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中,您将使用this存储SetWindowLongPtr对象以供将来使用。

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;
}