PDA

View Full Version : c++/win32 - static and callback



lsdi
07-05-2002, 09:12 PM
I have a Window class with a callback on it.
So each instance (window) must have its own callback(so callback cannot be static), but "wc.lpfnWndProc" requires a "static" member.

The error:



error C2440: '=' : cannot convert from 'long (__stdcall MYCLASS::*)(struct HWND__ *,unsigned int,unsigned int,long)' to 'long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long)'

Jambolo
07-05-2002, 11:07 PM
So you want to have a single class with several wndproc functions to choose from? That doesn't sound right. Or do you want to have a virtual wndproc and implement it in derived classes? That sounds better but it won't work in your case.
How about storing the address of the window in the user data field? Then have a static callback function in the base class which grabs the address and calls the real callback function (implemented in the derived class).

Robbo
07-06-2002, 12:34 AM
Your callback must be a static member. The solution is to use a map, to map instances to member functions and to execute the appropriate method.

Frameworks like MFC and ATL do this automatically, so you don't have to worry about all the WndProc rubbish.

knackered
07-06-2002, 04:42 AM
C++ does this automatically. Your class methods are merely static C functions, and the C++ precompiler invisibly passes in an instance argument every time you call one.
The Win32 framework is a C interface, so you have to do this yourself.

V-man
07-06-2002, 07:14 AM
>>> So each instance (window) must have its own callback(so callback cannot be static), but "wc.lpfnWndProc" requires a "static" member.<<<

Callbacks are static. They are your basic C style functions.

wc.lpfnWndProc=MYCLASS::function;

where function is declared static.

V-man

davepermen
07-06-2002, 11:08 AM
in createwindow you can give over an additional parameter, wich is the thispointer.
in the static messageproc you check for WM_NCCREATE and there, you look for this additional userparameter of createwindow (the CREATEWINDOWSTRUCT you ressieve in one param, i think the LPARAM). this this-pointer you got over there you store into your window with SetWindowLong(GWL_USERDATA,(long)_the_this_pointer _of_createwindow);

then, for all other messsages, use GetWindowLong(hwnd,GWL_USERDATA) to recieve the thispointer again, and call the nonstatic per window implemented HRESULT Window::WndProc(UINT msg,WPARAM wParam,LPARAM lParam);

thats the way that is the fastest and best one..

jwatte
07-06-2002, 01:11 PM
For MDI child windows, you need to pass a specific Windows struct as the lpParam parameter. I prefer to pass an actual CLIENTCREATESTRUCT but embellish with my own window pointer, something like:

struct MyCreateStruct {
IMyWindow * window;
CLIENTCREATESTRUCT mdiData;
};

Then you pass &myStruct.mdiData as lpParam, and recover the pointer to MyCreateStruct inside NCCREATE using pointer arithmetic.

lsdi
07-06-2002, 05:17 PM
davepermen;

do you have an example?

lsdi
07-06-2002, 05:33 PM
Hey guys. please help me. I Know theres an simple and object oriented solution for this problem.


Thanks a lot;

http://www.opengl.org/discussion_boards/ubb/biggrin.gif

davepermen
07-07-2002, 02:56 AM
have fun: http://www.itstudents.ch/users/dave/free/files/Window.zip
its now some time old, dunno. but it works..

it has more in than you want, but, its a working example http://www.opengl.org/discussion_boards/ubb/smile.gif

jwatte
07-07-2002, 05:37 AM
lsdi,

Because Win32 is a procedural interface, you have to interface with it procedurally. We've shown you two ways to minimize the procedural interface, both of which are good solutions to the problem of adapting the given procedural interface to some polymorphic interface of your choice.

dslater
07-08-2002, 06:51 AM
The Win32 API requires that a window procedure be a C function with no this pointer. There is no way around this. Your options are:
1) create a map that maps HWND's to C++ Object pointers and have your window procedure use this map to forward the messages to the C++ objects - this is how MFC does it.
2) do it the way ATL does it. - Basically what happens is that when the first message is received by a StartWindowProcedure, the C++ object that corresponds the the HWND is looked up and a thunk is created that hold's the C++ objects this pointer. SetWindowLong is then used to sub-class the window to use the thunk as the window procedure. What the thunk does is to replace the HWND parameter with the this pointer, then jmp to a Window procedure that casts the hwnd parameter to a CWindow pointer and call the CWindow's ProcessWindowMessage() method which is non-static. Hope this helps http://www.opengl.org/discussion_boards/ubb/smile.gif

Robbo
07-08-2002, 06:57 AM
Dslater, that sounded quite painfull. Does WTL do things any differently?

lsdi
07-08-2002, 09:01 AM
Davepermen, your method works VERY fine. Thanks.