Sign in to follow this  
Lenox

Message Handling Problem ( was "Problem in Game Loop?" )

Recommended Posts

Lenox    166
Hey, I'm having a problem. It seems I'm having problems with my message handling. I can't exit the application by hitting 'escape' unless I use GetAsyncKeyState(). Here's some code: Main.cpp
void Kernel::newWindow( int W, int H )
{
	HWND hWind = NULL;

	WNDCLASSEX windowClass;
	windowClass.cbSize			=			sizeof( WNDCLASSEX );
	windowClass.style			=			CS_HREDRAW | CS_VREDRAW;
	windowClass.lpfnWndProc		=			WndProc;
	windowClass.cbClsExtra		=			0;
	windowClass.cbWndExtra		=			0;
	windowClass.hInstance		=			hInstance;
	windowClass.hIcon			=			LoadIcon( NULL, IDI_APPLICATION );
	windowClass.hCursor			=			LoadCursor( NULL, IDC_ARROW );
	windowClass.hbrBackground	=			(HBRUSH)GetStockObject( BLACK_BRUSH );
	windowClass.lpszMenuName	=			NULL;
	windowClass.lpszClassName	=			"window";
	windowClass.hIconSm			=			LoadIcon( NULL, IDI_WINLOGO );

	if( !RegisterClassEx( &windowClass ) )
	{
		return;
	};

	hWind = CreateWindowEx( NULL, "#32769", "Audeuroa Adakitsa",
							WS_OVERLAPPEDWINDOW | WS_VISIBLE,
							0, 0, W, H, NULL, NULL, NULL, NULL );


	if( !( hWind ) )
	{
		return;
	}

	if( FAILED( initD3D( hWind, 800, 600 , true ) ) )
	{
		DestroyD3D();
		return;
	}; 

	++currIndex;
};

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
	try
	{

		kInst = new Kernel();

		kInst->setInst( hInstance );

		kInst->newWindow( 400, 400 );

		MSG msg;

		while( 1 )
		{
			while( PeekMessage( &msg, NULL, 0, 0, PM_NOYIELD | PM_REMOVE ) )
			{
				if( msg.message == WM_QUIT )
				{
					delete kInst;
                    return msg.wParam;
				};

//				TranslateMessage( &msg ); // We WANT to use Virtual Keycodes, so we MUST NOT call TranslateMessage
				DispatchMessage( &msg );
			}
/*
			if( GetAsyncKeyState( VK_ESCAPE ) )
			{
				break;
			};
*/
			Sleep( 1 );
		};
		
		delete kInst;
		return msg.wParam;
	}

	catch( gExceptionHandler::Exception )
	{
		MessageBox( NULL, "An exception occured, the program will now exit. Please send your Exception.log to BugCenter@Sineful.com.", "Exception" , MB_OK );
		return 0;
	}

	catch( ... )
	{
		MessageBox( NULL, "An exception occured. The program will now exit. " , "Exception" , MB_OK );
        return 0;
	}

};


// GetAsyncKeyState()
LRESULT CALLBACK WndProc( HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam )
{
	switch( Message )
	{
	case WM_KEYDOWN:
		{
			switch( wParam )
			{
			case VK_ESCAPE:
				{
					PostQuitMessage( 0 );
					break;
				};
			};

			return 0;
		};
		
	case WM_PAINT:
		{
			PAINTSTRUCT ps;
			HDC hdc;
			hdc = BeginPaint( hWnd, &ps );

			RECT rect;
			GetClientRect( hWnd, &rect );

			EndPaint( hWnd, &ps );

			break;
		};

	case WM_CLOSE:
		{

			return 0;
		};

	case WM_DESTROY:
		{
			PostQuitMessage( 0 );
			break;
		};

	};

	return DefWindowProc( hWnd, Message, wParam, lParam );
};






For some reason, WndProc isn't handling the messages properly. I can push escape and the quit message won't be posted. [EDIT] Fixed no-close problem: Thanks Palish! Updated code. Updated code with my newWindow procedure. Haha, fproto pointed out that I forgot to complete that return, :P. [Edited by - Lenox on June 4, 2005 2:22:27 AM]

Share this post


Link to post
Share on other sites
pragma Fury    343
You're in an infinite loop, so your application is running in circles as fast as it can, and doesn't care about any other applications on your system:

while( 1 )
{
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if( msg.message == WM_QUIT )
{
break;
}
TranslateMessage( &msg );
DispatchMessage( &msg );
};
};





If using 99% cpu is undesirable for your program, you can force your application to give up CPU control by using a Sleep(0) call. Though if you're writing a time-critical application, (aka graphics engine) you probably want all the CPU you can get.


while( 1 )
{
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if( msg.message == WM_QUIT )
{
break;
}
TranslateMessage( &msg );
DispatchMessage( &msg );
};

// give up CPU control to waiting threads
Sleep(0);
};





If you wish for your application to use as much CPU as it can, only when nothing else needs it, you can set the thread priority to idle:



SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE);

/*
... your program loop here
*/




Share this post


Link to post
Share on other sites
Lenox    166
pragma Fury:
Should it be taking up 99% since I have no rendering to do yet? I WILL take your Sleep( 0 ) advice.

Also, I found out why WM_KEYDOWN isn't being sent. For some reason, WndProc isn't even being called! Anyone know why? Thanks for any help in advance.

Share this post


Link to post
Share on other sites
Saruman    4339
Quote:
Original post by Lenox
Should it be taking up 99% since I have no rendering to do yet? I WILL take your Sleep( 0 ) advice.

1.) Yes it should be, you are in a loop.
2.) I'm not sure if you understood, but calling Sleep(0) is generally not something that you want to do in a game or graphics engine, you want full resources.

Share this post


Link to post
Share on other sites
Lenox    166
Quote:
Original post by Saruman
Quote:
Original post by Lenox
Should it be taking up 99% since I have no rendering to do yet? I WILL take your Sleep( 0 ) advice.

1.) Yes it should be, you are in a loop.
2.) I'm not sure if you understood, but calling Sleep(0) is generally not something that you want to do in a game or graphics engine, you want full resources.


I'm going to remove Sleep( 0 ) as soon as I actually have something to render.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
I agree with the original poster, I think 100% resources at all times is not a good idea for Windows games, because it's common to pause to check IM or email. You probably want to design your heaviest loads to run at >= 30fps, so it's quite reasonable Sleep during lighter loads. BTW, I use Sleep(1), because Sleep(0) tends to nearly max out the CPU anyway! A granularity of 1 to 2 milliseconds hasn't bugged me at all.

Share this post


Link to post
Share on other sites
Lenox    166
Quote:
Original post by Anonymous Poster
I agree with the original poster, I think 100% resources at all times is not a good idea for Windows games, because it's common to pause to check IM or email. You probably want to design your heaviest loads to run at >= 30fps, so it's quite reasonable Sleep during lighter loads. BTW, I use Sleep(1), because Sleep(0) tends to nearly max out the CPU anyway! A granularity of 1 to 2 milliseconds hasn't bugged me at all.



It worked. Sleep( 1 ) slowed it down to 0% CPU Usage as expected. Thanks. Now I just need help with why WndProc isn't being called.

Share this post


Link to post
Share on other sites
pragma Fury    343
Keep in mind that Sleep() (like GetTickCount()) has limited granularity.. if you type Sleep(1), your system will generally sleep for anywhere between 3 and 15ms!

In fact, if you have a CPU-greedy application running elsewhere, your program may not get control back for a couple hundred ms!

Best to avoid Sleep in any time-critical application.

You can pretty easily set your Thread Priority to idle, or intialize your Sleep-ing when your application loses focus.

Share this post


Link to post
Share on other sites
Lenox    166
Quote:
Original post by pragma Fury
Keep in mind that Sleep() (like GetTickCount()) has limited granularity.. if you type Sleep(1), your system will generally sleep for anywhere between 3 and 15ms!

In fact, if you have a CPU-greedy application running elsewhere, your program may not get control back for a couple hundred ms!

Best to avoid Sleep in any time-critical application.

You can pretty easily set your Thread Priority to idle, or intialize your Sleep-ing when your application loses focus.


Ah, I see. Thanks! ( Remember: Sleep( 1 ) is just a temporary fix. But, I will be doing long periods of sleep while the application is minimized. )

Share this post


Link to post
Share on other sites

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