Why can't my WndProc be in a class?

前端 未结 3 630
清酒与你
清酒与你 2021-02-05 18:29

This seems like it should be pretty straightforward. I have my class:

class Simple
{
public:
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPA         


        
相关标签:
3条回答
  • 2021-02-05 19:14
    // 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);  
    }  
    
    0 讨论(0)
  • 2021-02-05 19:30

    A pointer to a member function has an implicit first parameter of this, and so has a different signiture than a pointer to a 'free' function. See http://www.parashift.com/c++-faq-lite/fnptr-vs-memfnptr-types.html

    0 讨论(0)
  • 2021-02-05 19:34

    C++ treats member functions and free functions as different - member functions need to have access to a this pointer, and typically that's passed in as a hidden first parameter. Consequently, an n-argument member function would be most similar to an (n+1)-argument free function, which means that code trying to call your WndProc would pass in the wrong number of arguments.

    You can, however, declare WndProc as a static member function, which eliminates the this pointer. This code should work:

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

    Of course, this means you can't directly access the fields of the class. You could get around this by embedding a pointer to the class into the extra bytes reserved for each window instance, perhaps by using SetWindowLongPtr. Once you've done that, you can recover the receiver object pointer by writing something like this:

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

    Hope this helps!

    0 讨论(0)
提交回复
热议问题