Class-member functions as WndProc for Win32 Window... WTF?

Started by
7 comments, last by MrSandman666 20 years, 11 months ago
Well, here's the deal. I'm working on something like a very simple window manager for one of my projects. I have a window class "SYS_Win" which represents a window and which can create itself. This class will eventually work as a base class to derive other window classes from, so I have a virtual WndProc function as a member of this class, which is to be registered with the class as usual. This is the (abbreviated) class definition with the functions:

class SYS_Win
{
public:
        bool Create(int nWidth, int nHeight, int nBits, bool bFullscreen, char *title);
...
	
private:
	virtual LRESULT	CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
...
};
    
This is the registration of the class, which is done inside the afforementioned Create() function, which is obviously also a member of SYS_Win.

wc.style		= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;	
wc.lpfnWndProc		= WndProc;				
wc.cbClsExtra		= 0;					
wc.cbWndExtra		= 0;					
wc.hInstance		= GetModuleHandle(NULL);		
wc.hIcon		= LoadIcon(NULL, IDI_WINLOGO);		
wc.hIconSm		= LoadIcon(NULL, IDI_WINLOGO);		
wc.hCursor		= LoadCursor(NULL, IDC_ARROW);		
wc.hbrBackground	= NULL;					
wc.lpszMenuName		= NULL;					
wc.lpszClassName	= title;
wc.cbSize		= sizeof(WNDCLASSEX);
  
And no, it doesn't make any different whether WndProc() is private, protected or public. I can't even get it to work as a function pointer to a global function which is then associated with the class at runtime (though that may simple be me not being able to handle function pointers...)! When I compile this I get something like

'=' : 'long (__stdcall SYS_Win::*)(struct HWND__ *,unsigned int,unsigned int,long)' can not convert to 'long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long)' 
 
And it doesn't let me typecast the function to WNDPROC either... Thanks a lot in advance. I'm really stuck with this one. ----------------------------- "Mr Sandman bring me a dream" [edited by - MrSandman666 on May 5, 2003 3:17:38 PM]
-----------------------------"Mr Sandman bring me a dream"
Advertisement
It's gotta be static. Check out the windows wrapper tutorial in the Articles & Resources section as for why.

I also have a fairly decent basecode available on my website, on the right panel somewhere.

[EDIT] Ok my site is broken... I'll check it out when I get home. It's losely based on this; however.


[My site|SGI STL|Bjarne FAQ|C++ FAQ Lite|MSDN|Jargon]
Ripped off from various people

[edited by - wild_pointer on May 5, 2003 3:27:56 PM]
[size=2]
Member functions take an extra parameter ''this'' that is hidden. In order to treat it as a normal function and use it for a normal function pointer, you''ll need to make it static. That means it won''t know which class it belongs to when its called. To fix that you either need to pass ''this'' on window creation and use SetWindowLong and then GetWindowLong to get the pointer on another message, or use a global map that maps HWNDs to pointers to the base window class.
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
you don''t even need a wndproc function. I just use a peek/translate message pump. works for me since i don''t use many windows messages..(just wm_size and the like)
I love me and you love you.
Sounds like a good solution, wild_pointer. I didn''t get the others to work in my sense so I will use your method.
(using static caused some other problems related with the overall design)

However, what do you pass for WndProc to the WNDCLASS structure? Passing NULL creates Access Violations. Do I have to pass a dummy function or is there a more elegant way?

-----------------------------
"Mr Sandman bring me a dream"
-----------------------------"Mr Sandman bring me a dream"
Look up the MUD Pies Part I: Let''s make a MUD Server source for a good example of how to use a static WndProc with SetWindowLong and GetWindowLong to pass messages around.
Argh! Shouldn''t be posting so late in the night... of course I meant I wanted to take Grizwald''s approach.
I can not use the static approach since I want to have different WndProcs for different instances of the class and because, well, you can''t make a satic function virtual, which would be somewhat necessary for my concept.

SO, I would like to take the message handling out of Windows'' hands and into mine by not using the standard message processing crap and instead go with the tuned-down Message Peek/Translate pump. However, I can''t pass a NULL to the WNDCLASS structure, since it generates Access Violations upon window creation. Is there a way to avoid using a dummy WndProc?

Warm regards...

-----------------------------
"Mr Sandman bring me a dream"
-----------------------------"Mr Sandman bring me a dream"
You can do what (I think) you want, you just have to do it in a slightly roundabout way.

Define your base class with a non-static WndProc function, but you don't pass this to RegisterClassEx. Instead, you create a simple static/non-member window procedure that looks something like this:


    INT CALLBACK StaticWindowProc(HWND hWnd, UINT msg,WPARAM wParam,LPARAM lParam){   MyBaseClass* p = (MyBaseClass*)GetWindowLong(hWnd,GWL_USERDATA);   if(p)   {      return p->WindowProc(hWnd,msg,wParam,lParam);   }   else   {      return CallWindowProc(DefWindowProc,hWnd,msg,wParam,lParam);   }}    


You just need to make sure that you call SetWindowLong() after you create the window to make sure the window is associated with a pointer to the appropriate class. Once you've done this, you can derive from your base class and take full advantage of polymorphism in your window handling system.

EDIT: Duh, it looks like this approach has already been suggested.

As for passing something to RegisterClass() without creating a dummy window proc, you could always just pass DefWindowProc.

[edited by - Sandman on May 6, 2003 9:37:52 AM]
Ok, thanks guys, I got it now. I was just being really stupid. Anyhow, now it works and I fell good. Thanks a lot!

-----------------------------
"Mr Sandman bring me a dream"
-----------------------------"Mr Sandman bring me a dream"

This topic is closed to new replies.

Advertisement