Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 823
  • 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

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

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