Sign in to follow this  

Do away with WndProc() in the msg loop?

This topic is 4162 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I might be a little(...) sleep deprived, but I was rethinking my program design in whole, and I was wondering why precisely I need WndProc(). As I see it, the windows message loop is like this:
while(msg.message!=WM_QUIT)  {
	if(PeekMessage(&msg,0,0,0,PM_REMOVE))  {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	Process();//or render or whatever you may want to do
}
So if there's a message, you remove it from windows' internal queue, translate and dispatch it so that windows can call your little personal function. Why not just call PeekMessage() and TranslateMessage() (translate only if you want the character messages), and then instead of dispatching, just process the message within your WinMain() or whatever, and assign 0 to WNDCLASS::lpfnWndProc when calling RegisterClass()? Is it just more standard? Or is there a technical reason that I overlooked? For example-
while(msg.message!=WM_QUIT)  {
	if(PeekMessage(&msg,0,0,0,PM_REMOVE))  {
		switch(msg.message)  {
		}
	}
	Process();//or render or whatever you may want to do
}
Edit - Anyone notice how the time zones etc for posts are different from those of the edits? Something I've seen for a while now, just curious if anyone else has. [Edited by - CrazyCamel on July 21, 2006 4:27:32 AM]

Share this post


Link to post
Share on other sites
One reason is that Windows will send you lots more messages than you'll actually process in your switch structure, and Windows will need to know this and do some processing itself. For instance, how is Windows supposed to know when someone pressed the minimize button (or moved your window) if you just throw the message away?

You don't need the message handling code in a switch statement, if that's what's bothering you. You could register a map structure with callback functions for each message you would like to process, thus cutting drastically on internal dependencies.

Share this post


Link to post
Share on other sites
Well for the messages I don't process, I'd call DefWindowProc() like most do in their normal window procedure callback function.

The thing that's "bothering" me isn't the switch statement. I have no problem with c++ syntax =). It just strikes me as a bit odd that everyone is putting their msg loop to a whole other function (ie WndProc), and that function is supported by msdn and is a callback function and everything... I dunno, it just seems silly and overcomplicated.

Edit- Also, after a bit more googling, it strikes me as odd that no one has stopped to ask this before? (as far as I have found yet)

Share this post


Link to post
Share on other sites
Interesting concept, this will also mean that wrapping your game window in a class will also be easier, as you do not have WndProc() to deal with.

The thing is will Windows allow a window to be created with WndProc() set to NULL. Never tried it myself.

Share this post


Link to post
Share on other sites
Windows will send a bunch of messages to your WndProc, that it doesn't hand you through Get/PeekMessage().

Any message sent using SendMessage() (instead of PostMessage()) will be dispatched directly to the WndProc, instead of going through the message pump.

Share this post


Link to post
Share on other sites
Talib-
Well it should; the only place windows calls your WndProc is when you call Dispatch message. If RegisterClass() or any other function fails because of a NULL function pointer, just give it a pointer to this:
LRESULT CALLBACK WndProc(HWND hwnd,unsigned int msg,WPARAM wParam,LPARAM lParam){return 0;}
*Waves goodbye to WndProc()*

hplus0603-
Is SendMessage() the only thing that has wndproc called directly? If it is, then (depending on specific application) ways could be found to work around that.

Edit - Also, if there happens to be a SendMessage() sent by another program or whatever, you could just return DefWindowProc() from the bogus WndProc function instead of 0, which would handle the basics. Anything other than basics would be specific... and specifics are hard to discuss unless talking about a specific specific... wait a minute... yes, that makes sense.

Share this post


Link to post
Share on other sites
Quote:
Original post by CrazyCamel
Is SendMessage() the only thing that has windows call wndproc? If it is, then (depending on specific application) ways could be found to work around that.
Windows may well call your wndproc directly for various things (I can't think of any offhand though). And I'm fairly sure components other than your application will call SendMessage(), meaning you'd have to have some sort of code in your WndProc.

Even if it seems to work, the effort of testing it properly (I.e. for every single combination of window message) will outweigh the benifits of not having a seperate function.

Also, your program is far less likely to work on future versions of Windows.

Share this post


Link to post
Share on other sites
Hm, what if you set WNDCLASS::lpfnWndProc to DefWindowProc? You give all the direct calls of WndProc to default, and you process all the others, right?

What other components would send messages to my application? Does anyone know any of the "various things" windows may call my WndProc for?

Edit - I don't mean to sound rude; I'm really curious as to whether any of this is viable.

Share this post


Link to post
Share on other sites
Well, if you are not using any other components IE a DX game, you fairly have major control of what is being sent in your application. Might still be viable.

Not that I am going to rewrite the my current method of wrapping my game window in a class and it's current use of messages (unless there are major speed advantages). It works perfectly as is.

Share this post


Link to post
Share on other sites
What about messages that require you to return certain values to indicate success or failure and so on? I don't believe the MSG structure contains any capacity for a return value, not is there any way to return values directly without a WndProc as far as I can see.

Plus, as has been said, Microsoft are within their rights to assume that legacy code is using a WndProc and make changes in the future that do depend on it, even if it is not necessary at the moment.

Share this post


Link to post
Share on other sites
Quote:
Original post by CrazyCamel
Hm, what if you set WNDCLASS::lpfnWndProc to DefWindowProc? You give all the direct calls of WndProc to default, and you process all the others, right?


lol you can do that but how are you going to rearrange child windows when they need to be moved (WM_SIZE is sent so when the parent is resized how are you going to know when to move/resize the children)? how are you going to exit your application (since WM_CLOSE, WM_DESTROY, and WM_NCDESTROY are sent you need another way to tell if your application needs to exit as DefWindowProc will not call PostQuitMessage)?

Share this post


Link to post
Share on other sites
I've read that D3D hooks into your window's winproc and receives messages before you do. If it relied on any posted messages, you'd skip the D3D code, quite possibly breaking your app.

Another thing DispatchMessage handles is calling the correct proc for each window, in a multi-window app. Lets say someone posted a message to your edit box. You now how to check if it's an application window message, or a standard control, and either call the control's winproc (DispatchMessage these I suppose), or find the appropriate function for that app window, and call it.

Or you could stick with the standard DispatchMessage(), ensuring your app works as expected, and ensuring others can read it. If you want a wndproc in a class, it's easy enough. Set the window's userlong value to your class pointer. Have a wndproc that just fetches the userlong, casts it to your window base class and calls it's virtual wndproc. All windows can now have customized wndprocs, as member functions, with a minimal single C style window proc in the way.

Share this post


Link to post
Share on other sites
If you do not follow Microsoft's recommended design for calling their API, Microsoft makes no guarentees that your application will function.

What happens if you recieve a WM_QUERYENDSESSION message? How are you expecting to return a value from your message pump? Are you just going to prevent the user from ever shutting down their computer? (Edit: I see now that EasilyConfused noted this before)

Don't be cute, don't be clever, do what's right and follow the rules and no one gets hurt. Be clever only when you absolutely must, not "because you can". You'll get very, very burned, otherwise. Either you, or someone who has to maintain your code, or your customers when it doesn't work on vista or some other operating system.

[Edited by - Erzengeldeslichtes on July 21, 2006 12:56:15 PM]

Share this post


Link to post
Share on other sites

This topic is 4162 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this