Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 834
  • Last Modified:

Encapsulating WndProc message processing callback in a class

Currently, i'm writing a class wrapper for the basic Win32 API functions that create windows, a menu, and a few controls. I know I could use MFC, but i'm learning much more doing it this way.

I'd like to include the standard message processing callback as a method in my window class, but haven't been able to get it to compile. A cut down version of what i'm talking about is here:

// class descriptor
class WindowsGui {
public:
    WindowsGui(HINSTANCE hInstance, int iCmdShow, const char* cClassName);
    virtual ~WindowsGui();

private:
    WNDCLASS _WndClass;
    LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
};

// Constructor
WindowsGui::WindowsGui(HINSTANCE hInstance, int iCmdShow, const char* cClassName)
{
    _WndClass.lpfnWndProc = WndProc;
}

// Callback method
LRESULT CALLBACK WindowsGui::WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
    return 0;
}

I've cut out all non-relevant parts. When I try to compile I get an error stating that the assignment to lpfnWndProc cannot complete as a type mismatch has occured between (LRESULT)(WindowsGui::*) and (LRESULT)(*). I've tried many different ways around this including different casts and using the 'this' operator, but I think my basic understanding of whats going on here is a little lacking.

Can anyone offer advice on what cast or fix can be applied either in the assignment of lpfnWndProc, or how I encapsulate the WndProc function into a method in my class?

Thanks for any advice
salukibob
0
salukibob
Asked:
salukibob
2 Solutions
 
jkrCommented:
The problem is that you can't use a non-static member function for a callback, since they're passed an invisible 'this' parameter so that the signatures won't match. The possible solutions are:

- use a static member
- use an adapter, see e.g. http://www.codeproject.com/win32/callback_adapter.asp ("Use member functions for C-style callbacks and threads - a general solution")
0
 
itsmeandnobodyelseCommented:
>>>> The problem is that you can't use a non-static member function for a callback  

jkr is right. Add the keyword static to the declaration of the member function

   static LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);

to get it compiled.

However, as the callback function now is a static function you need to retrieve somehow the instance of class WindowsGui, the hWnd was associated to. Normally, you would do such a thing by implementing a global map where hwnd is the key and the pointer to WindowsGui is the data. You also could do that by a little 'Manager' class:

class GuiManager
{
     std::map<HWND, WindowsGui*> hwndMap;
public:
     void register(HWND hwnd, WindowsGui* pWnd) { hwndMap[hwnd] = pWnd; }
     void unregister(HWND hwnd) { hwndMap.erase(hwnd); }
     WindowsGui* lookup(HWND hwnd)
     {
          map<HWND, WindowsGui*>::iterator it = hwndMap.find(hwnd);
          if (it != hwndMap.end())
                return it->second;
    }
    return NULL;
};

// the one and only GuiManager
extern  GuiManager theGuiManager;


// in windowsgui.cpp

#include "guimanager.h"

// the one and only GuiManager
GuiManager theGuiManager;      // needs to get defined in one cpp file (without extern keyword)

If doing so, you can retrieve the WindowsGui object in the callback function by

// Callback method
LRESULT CALLBACK WindowsGui::WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
    WindowsGui* pWnd = theGuiManager.lookup(hWnd);
   
    if (pWnd != NULL)
    {
           // we found the object!
           ...
    }
    return 0;
}


Regards, Alex
0
 
salukibobAuthor Commented:
Thanks for the advice. I see what you mean, and I can see now that I was missing the point that I will only want one message processing function, not one with each object created. Hence the static. Thanks also for the additional pointers.

Points split.

Regards
salukibob
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

Tackle projects and never again get stuck behind a technical roadblock.
Join Now