为什么我的WndProc不能上课?

sir*_*lot 11 c++ winapi

这看起来应该非常简单.我上课了:

class Simple
{
public:
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
         ...
    }
};
Run Code Online (Sandbox Code Playgroud)

和我的WinMain:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR commandLine, int cmdShow)
{
    Simple *simple = new Simple();
    ...

    wndClass.lpfnWndProc = simple->WndProc;
    ...
 }
Run Code Online (Sandbox Code Playgroud)

当我尝试时,我得到:

error C2440: '=' :cannot convert from 'LRESULT (__stdcall Simple::* )(HWND,UINT,WPARAM,LPARAM)' to 'WNDPROC'
Run Code Online (Sandbox Code Playgroud)

有什么理由我不能WndProc上课吗?看起来那样真的很有用.

tem*_*def 26

C++将成员函数和自由函数视为不同 - 成员函数需要访问this指针,并且通常将其作为隐藏的第一个参数传入.因此,n参数成员函数最类似于(n + 1) - 自由函数,这意味着试图调用你的代码WndProc将传递错误数量的参数.

但是,您可以将其声明WndProcstatic成员函数,从而消除this指针.这段代码应该有效:

class Simple
{
public:
    static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
         ...
    }
};

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR commandLine, int cmdShow)
{
    Simple *simple = new Simple();
    ...

    wndClass.lpfnWndProc = simple->WndProc;
    ...
 }
Run Code Online (Sandbox Code Playgroud)

当然,这意味着您无法直接访问该类的字段.您可以通过将指向类的指针嵌入到为每个窗口实例保留的额外字节中来解决这个问题,可能是通过使用SetWindowLongPtr.完成后,您可以通过编写以下内容来恢复接收器对象指针:

class Simple
{
public:
    static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
         Simple* me = static_cast<Simple*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
         if (me) return me->realWndProc(hwnd, msg, wParam, lParam);
         return DefWindowProc(hwnd, msg, wParam, lParam);
    }
private:
    LRESULT CALLBACK realWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
         // Yay!  I'm a member function!
    }
};
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!

  • 哇,这奇迹般地奏效了!非常非常棒,比我见过的单例方法要好得多。我只是在创建 HWND 后添加了这一行: SetWindowLongPtr(hwnd, GWLP_USERDATA, (long)this); (2认同)