Why does WndProc() have to be global ??

Started by
10 comments, last by Sir_Spritely 20 years ago
I realise there are ways to incorperate WndProc() into a class but as far as I can tell there must always be a global WndProc(). I have done a lot of reading on this and some of the explanations are mind boggling. I know it is something to do with the O.S calling the Wndproc() function and as such no THIS pointer is passed. Wondering if anyone can explain in detail yet simply about this issue.
Advertisement
The WndProc does not need to be a global function, a static member function works too.

The OS must be able to call the WndProc, therefore calling convention and parameters must exactly match. Non-static class member functions always have a hidden first parameter, the this pointer.
If the WndProc() is declared as static that means it can not access non-static members. Making this method ineffective though?
Yes, a static function works almost like a global one.
That is exactly why people choose to use a thunk in its place. When you use a thunk, you basically rename the function so it doesn''t have the this pointer in it. You should be able to find some material online about it from a google search if you want to know more.

On a side note, I believe you can make it a friend (or something like that) have the function work too, but if my memory serves me right it will act the same as if it was static.

-brad
-brad
quote:Original post by Sir_Spritely
If the WndProc() is declared as static that means it can not access non-static members. Making this method ineffective though?


It''s tidier to use a static function than using a global function if you want to write a class wrapper. Also, you can access other static class members simpler than from a global function and it''s tidying up the code.
Can someone please read this and let me know if I have this right or correct where neccasary (Thanks for the help!)


There is a slight issue when using OOP and Windows with the WndProc() function which is as previously stated the event handler where all messages head to first. Various windows based applications use this global function in various ways. In our case this function is used as a message command centre and when messages are recieved via this function it delegates the messages out to the Msgproc() member function of the derived Application class. In the Windows structure WNDCLASSEX, the default window procedure which processes all of the applications (the window which is created) messages. Now this function is known as a Callback function meaning it is called by the Operating System and not another function. Anytime a message is generated and has to be dealt with the Windows Operating System will send the message to the WndProc() function specified in the WNDCLASSEX structure. Thus the WndProc() function is actually being called by the Windows Operating System and not the object or indeed any function associated with the application. So a Callback function such as the WndProc() does not operate on a particular object and is as such Global. All the neccasary parameters the Callback function needs are passed to it by the Windows Operating System. Hence we can say a Callback function which includes WndProc() is a global function because it does not operate on any particular object. On the other hand a member function actually does implicitly operate on a particular object and usually has the object on which it is to operate on passed to it implicitly. By this I mean the object on which it is to operate on is passed in the form of a hidden first parameter known as the THIS pointer. So WndProc() cannot be a member function because a member function always has the hidden THIS pointer as it''s first parameter. When the Windows Operating System calls the Callback function like WndProc() and tries to pass the various parameters the function needs it comes across a different function prototype. Thus a compile error is caused. It is entirely possible to make the WndProc() a member function and make it accessible by the Windows Operating System. This can be achieved by making the WndProc() member function static, this removes the hidden THIS pointer parameter so the prototype matches the one the Windows Operating System is looking to call. However another problem is then raised in that this function because it is declared as being static cannot access any instance variables (an object of the class).
Heres how I used it as a static function with access to member variables for all messages after WM_CREATE

you just have to pass the window as the lpParameter in the CreateWindowEx Function

static LRESULT WINAPI XWindow::WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam){	XWindow * w;	int i;	w = (XWindow *)GetWindowLong(hWnd, GWL_USERDATA);	switch(Msg)	{	case WM_CREATE:		{			CREATESTRUCT * cs;			cs = (CREATESTRUCT *)lParam;			w = (XWindow *)cs->lpCreateParams;			SetWindowLong(hWnd, GWL_USERDATA, (LONG_PTR)w);		}		break;	case WM_DESTROY:		w->m_IsWindow = false;		break;	}// Execute my own message map	if(w != Null)	{		w->m_wParam = wParam;		w->m_lParam = lParam;		for(i = 0; i < (int)w->m_MsgMap.GetSize(); i++)		{			if(w->m_MsgMap[i]->m_Msg == Msg)			{				w->m_MsgMap[i]->m_Function(w);			}		}	}	return DefWindowProc(hWnd, Msg, wParam, lParam);}


[edited by - Ximmer on March 27, 2004 7:39:16 AM]
I wrote an article for GameDev a good while ago: Creating a Win32 Window Wrapper Class. Some of its specifics may be overkill, but it explains the fundamental principles adequately.
Basicly it's hard then?

[edited by - Stevieboy on March 27, 2004 6:45:46 PM]

This topic is closed to new replies.

Advertisement