14

这似乎应该很简单。我有我的课:

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

我的WinMain

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

    wndClass.lpfnWndProc = simple->WndProc;
    ...
 }

但是,当我尝试时,我得到:

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

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

4

3 回答 3

31

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

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

class Simple
{
public:
    static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
         Simple* me = reinterpret_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!
    }
};

希望这可以帮助!

于 2013-06-20T19:13:12.783 回答
1

指向成员函数的指针具有隐含的第一个参数this,因此与指向“自由”函数的指针具有不同的符号。见http://www.parashift.com/c++-faq-lite/fnptr-vs-memfnptr-types.html

于 2013-06-20T19:13:44.520 回答
0
// Header  
class Foo   
{  
public:
  Foo();   

  ~Foo();  

  static LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);

private:
  LRESULT CALLBACK MyWinProc(HWND, UINT, WPARAM, LPARAM);

  static Foo *m_pInstance;
}

// Implementation

#include "Foo.h"

Foo * Foo::m_pInstance = NULL;

Foo::Foo()
{  
  m_pInstance = this;   
}  

Foo::~Foo()
{
}

LRESULT CALLBACK Foo::WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  
{  
  return m_pInstance->MyWinProc(hWnd, message, wParam, lParam);  
}  

LRESULT CALLBACK Foo::MyWinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  
{  
  return DefWindowProc(hWnd, message, wParam, lParam);  
}  
于 2014-11-05T22:51:24.087 回答