为什么我的WndProc不能上课?

时间:2013-06-20 19:08:57

标签: c++ winapi

这似乎应该非常简单。我有我的班级:

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?看起来真的很有用。

3 个答案:

答案 0 :(得分:25)

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

但是,您可以将WndProc声明为static成员函数,这会消除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 = 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!
    }
};

希望这有帮助!

答案 1 :(得分:1)

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

答案 2 :(得分: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);  
}