Solved

Encapsulating WndProc message processing callback in a class

Posted on 2006-11-22
3
779 Views
Last Modified: 2008-02-01
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
Comment
Question by:salukibob
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
3 Comments
 
LVL 86

Accepted Solution

by:
jkr earned 60 total points
ID: 17997450
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
 
LVL 39

Assisted Solution

by:itsmeandnobodyelse
itsmeandnobodyelse earned 65 total points
ID: 17997787
>>>> 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
 

Author Comment

by:salukibob
ID: 17997998
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

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

749 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question