Sign in to follow this  

win32: Alternative message loop

This topic is 4248 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

First off: Hello, I'm new here but I've been reading the forums every now and then and found them tremendously useful :) And now about the problem... Before I want to dive into directx and opengl and all that I want to make sure I know enough win32 programming to be sure that won't be a problem for any future games. Thus, it has been my ideal to create an easy wrapper class, that'd make creating windows no more difficult than: OpenWindow ( some params ); I know there's a tutorial on this site about making such a class, but I want to do things different and before I'm actually going to create the class I am testing with alternative message loops to make the job easier. I came up with the following:
#include <windows.h>
#define WIN32_LEAN_AND_MEAN

// start the main window loop immediately
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{

	// Create a MSG struct instance
	MSG msg;

	// Create a WNDCLASSEX struct instance
	WNDCLASSEX wc;

	// Create a window handle
	HWND hWnd;

	// Fill the members of the WNDCLASSEX struct
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.style = NULL;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.lpfnWndProc = DefWindowProc;
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor = LoadCursor(hInstance,IDC_ARROW);
	wc.hIcon = LoadIcon(hInstance,IDI_APPLICATION);
	wc.hIconSm = LoadIcon(hInstance,IDI_APPLICATION);
	wc.hInstance = hInstance;
	wc.lpszClassName = "MyWindow";
	wc.lpszMenuName = NULL;
	
	// Register the actual class...
	if ( !RegisterClassEx ( &wc ) ) {
		MessageBox ( NULL, "Could not register window class!\nThis program will close now.", "Fatal Error", MB_OK|MB_ICONEXCLAMATION );
		return 0;
	}

	// Open a window and show it
	hWnd = CreateWindowEx ( WS_EX_OVERLAPPEDWINDOW, "MyWindow", "Test Window", WS_SYSMENU|WS_VISIBLE|WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL );
	if ( hWnd == NULL ) {
		MessageBox(NULL,"Could not open window display!\nThis program will close now.", "Fatla Error", MB_OK|MB_ICONEXCLAMATION);
	}

	ShowWindow ( hWnd, nCmdShow );
	UpdateWindow ( hWnd );
	
	// Now the ingenious part... The while message loop...
	int quit = 0;
	
	while ( quit == 0 )
	{		

		if ( PeekMessage ( &msg, hWnd, 0, 0, PM_REMOVE ) ) {

			TranslateMessage ( &msg );
			DispatchMessage ( &msg );

		}

		if ( msg.message == WM_QUIT  ) {

			PostQuitMessage ( 0 );

			quit = 1;

		} 
		
	}

    return 0;
}

Basically, the idea is to put the message loop inside the main window loop because I want my future windows program to look like this:
#include "mywinwrapclass.h"

OpenWindow ( "My Window Name", x, y, width, height );

While ( GetWindowMessage() != WM_QUIT ) {

  // do some stuff

}

Please note that the GetWindowMessage() function would be 'self-made'. Now, for the actual problem... I use VS6 and the first codeblock (the 'alternative message loop' test program) runs fine. It opens a window, and when you press the X button it closes. At least the window disappears, about the actual closing i'm not so sure because when I open my task manager I see that the CPU is on 100% and the program (WinLoop.exe) is taking it's full attention and looks far from being closed... :S Is there something I'm missing? Must I free the window class or something because I didn't use a normal windows callback function?

Share this post


Link to post
Share on other sites
You should really have an own WindowProc, because SendMessage bypasses GetMessage and calls the window proc directly.

Also, PeekMessage doesn't retrieve the WM_QUIT event (you need GetMessage for that). So your program doesn't know that it should end and goes on and on forever.


if ( msg.message == WM_QUIT ) {
PostQuitMessage ( 0 );
quit = 1;
}


PostQuitMessage posts the quit message. This usage is quite senseless (if it would work, it would send a WM_QUIT message in response to a WM_QUIT message, which would lead to an endless loop.

A better way would to write a WindowProc and then respond to the WM_CLOSE and WM_DESTROY messages:


LRESULT CALLBACK myWindowProc( HWND wnd, unsigned int msg, LPARAM, WPARAM )
{
switch (msg) {
case WM_CLOSE: DestroyWindow( wnd ); return TRUE; break;
case WM_DESTROY: PostQuitMessage( 0 ); return TRUE; break;
default: break;
}
return DefWindowProc( wnd, msg, lp, wp );
}

Share this post


Link to post
Share on other sites
Thanks for the quick replies. The first one didn't work, unfortunately, but Konfusius' suggestion did the trick ;)

EDIT: Bah, I was a bit too enthusiastic to see that though the processor had gone back to its usual 2-4% the .exe was still running according to the taskmanager :( Below is the new way of doing the message loop, should I let the winmain function return something different? I'm a bit baffled that a normal window callback that returns 0 when the wm_destroy message is being processed does the job better than a simple 'if ( msg.message == wm_destroy )'...




Basically, I still want to experiment without the usual window callback function, but your endless loop advice from PostQuitMessage(0) was quite welcome. I now used GetMessage instead of PeekMessage and the messageloop now looks like this:

while ( quit == 0 ) {

if ( GetMessage ( &msg, NULL, 0, 0 ) > 0) {

TranslateMessage ( &msg );
DispatchMessage ( &msg );

}

if ( msg.message == WM_CLOSE ) {

DestroyWindow ( hWnd );

}

if ( msg.message == WM_DESTROY ) {

PostQuitMessage ( 0 );

}

if (msg.message == WM_QUIT) {

quit = 1;

}

}

It works perfectly, thanks. I think I can finally get on with creating the actual wrapper, and though I'm a bit concerned about your note on SendMessage() sending messages immediately to the callback function I'm hopeful that there will be ways around that ;)

[Edited by - rogierpennink on April 29, 2006 7:17:10 AM]

Share this post


Link to post
Share on other sites

This topic is 4248 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