confused with peekmessage and looping

Started by
7 comments, last by miggs 13 years, 8 months ago
hi

i built a inputmanager class, that has an update() method which is being called in my game loop. my problem is, i'm not really sure whether i'm placing my code in the right place and whether it is organized well.


my inputmanger::update() looks like:
{
if (msg.message == WM_QUIT)
this->quit = true;

TranslateMessage(&msg);
// is here the right place to call my own functions like:
// MouseHandler(msg);
// KeyboardHandler(msg);
// who then deal with the WM and VK events
DispatchMessage(&msg);
}

or am i mixing up stuff and approching it wrong? i read of some keyboard/mouse handler hooked functions, but im new to this and wouldn't know how.


thanks for your help
Advertisement
Why don't you do so from the Window Procedure function? Take the message apart and send the parameters as arguments.

Yo dawg, don't even trip.

how could i take them apart?

and do you mean simple function calls to my inputmanager->mouseHandler(wparam, lparam...) functions, or callbacks?

because all i see in examples are callbacks and i don't quite understand.

and do you mean this windows procedure?
WNDCLASSEX wincl;
...
wincl.lpfnWndProc = WindowsGUI::WindowProcedure;
...

?
Quote:Original post by miggs
and do you mean this windows procedure?
WNDCLASSEX wincl;
...
wincl.lpfnWndProc = WindowsGUI::WindowProcedure;
Yes, that's what boogyman is referring to (presumably).

Can you post the code for WindowsGUI::WindowProcedure()?
Quote:
LRESULT CALLBACK WindowsGUI::WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the messages */
{
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}

return 0;
}


pretty straigt forward. i didn't know what and where so it's untouched. could you give me a push to the right direction? what about those callbacks i read everywhere? or should i just call my own methods directly from here?

and should i put the peekmessage loop in here or how's it meant? because then, it would be in a thread like function or am i wrong? and then i don't know how to implement it back to my game loop. :/
DispatchMessage will automatically call your WndProc for you, with information on the message.

Minimal example of how I usually do it:
#include <windows.h>LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);// Global color variableCOLORREF g_color;// Mainint WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {	// Register windowclass	WNDCLASSEX wc;	ZeroMemory(&wc, sizeof(wc));	wc.cbSize = sizeof(wc);	wc.lpszClassName = TEXT("MyClass");	wc.hInstance = hInstance;	wc.lpfnWndProc = WndProc;	wc.hCursor = LoadCursor(NULL, IDC_ARROW);	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);	RegisterClassEx(&wc);		// Create window	HWND hWnd = CreateWindowEx(	0, wc.lpszClassName, TEXT("My Window"), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,	CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);		// Main loop	ShowWindow(hWnd, nCmdShow);	while(true) {		MSG msg;		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0) {			if(msg.message == WM_QUIT)				break;			else {				// Handle a message				TranslateMessage(&msg);				DispatchMessage(&msg);// This will call WndProc if needed			}		}		else {			// ... Here handle one frame ...			// cause there's no message to be handled right now			HDC hDC = GetDC(hWnd);			RECT rect;			SetRect(&rect, 50, 50, 250, 250);			HBRUSH hBrush = CreateSolidBrush(g_color);			FillRect(hDC, &rect, hBrush);			DeleteObject(hBrush);			ReleaseDC(hWnd, hDC);		}	}		UnregisterClass(wc.lpszClassName, hInstance);		return 0;}// Window procedure// DispatchMessage(&msg) will call this function for youLRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {	switch(msg) {		// Window destroyed.		case WM_DESTROY:			PostQuitMessage(0);		return 0;				// Key pressed		case WM_KEYDOWN:			switch(wParam) {				case VK_SPACE:					g_color = RGB(rand(), rand(), rand());				return 0;								case VK_ESCAPE:					DestroyWindow(hWnd);				return 0;			}		break;	}		return DefWindowProc(hWnd, msg, wParam, lParam);}
edit: delete first few sentences, clear now, still further question:


extending your example, i can't execute my dynamic class inputmanager handler functions from the static wndproc can i?

[Edited by - miggs on August 20, 2010 7:56:08 PM]
Quote:Original post by miggs
you have an "if(peekmessage..", doesn't that mean, that only 1 message per game loop is read now?


Since a game-frame is only handled in an else {, that doesn't matter. You could write it with a while() instead if you want, it doesn't matter. Just remember to break out of the outer while-loop on WM_QUIT if you do.

Quote:extending your example, i can't execute my dynamic class inputmanager handler functions from the static wndproc can i?


Yes you can, however it requires some extra work. Each window-handle has user-data associated with it, that you can set and get with SetWindowLongPtr and GetWindowLongPtr. These can be used to store a pointer to your dynamic inputmanager.

Here's an updated example which sets the user-data. Often some WindowHandler class implements the whole WndProc, and the static one just calls that one. There are different ways to implement it, pick one that suits you.
#include <windows.h>LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);// Custom class to contain data for a windowclass MyWindowData {	public:		void setColor(COLORREF color) {			m_color = color;		}				COLORREF getColor() {			return m_color;		}		private:		COLORREF	m_color;};// Mainint WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {	// Register windowclass	WNDCLASSEX wc;	ZeroMemory(&wc, sizeof(wc));	wc.cbSize = sizeof(wc);	wc.lpszClassName = TEXT("MyClass");	wc.hInstance = hInstance;	wc.lpfnWndProc = WndProc;	wc.hCursor = LoadCursor(NULL, IDC_ARROW);	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);	RegisterClassEx(&wc);		// Create window-data object	MyWindowData *myWindowData = new MyWindowData;		// Create window, pass the window-data object as last parameter	HWND hWnd = CreateWindowEx(	0, wc.lpszClassName, TEXT("My Window"), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,	CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, myWindowData);		// Main loop	ShowWindow(hWnd, nCmdShow);	while(true) {		MSG msg;		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0) {			if(msg.message == WM_QUIT)				break;			else {				// Handle a message				TranslateMessage(&msg);				DispatchMessage(&msg);// This will call WndProc if needed			}		}		else {			// ... Here handle one frame ...			// cause there's no message to be handled right now			HDC hDC = GetDC(hWnd);			RECT rect;			SetRect(&rect, 50, 50, 250, 250);			HBRUSH hBrush = CreateSolidBrush(myWindowData->getColor());			FillRect(hDC, &rect, hBrush);			DeleteObject(hBrush);			ReleaseDC(hWnd, hDC);		}	}		UnregisterClass(wc.lpszClassName, hInstance);		return 0;}// Window procedure// DispatchMessage(&msg) will call this function for youLRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {	switch(msg) {		// Window created		case WM_NCCREATE: {			// lParam contains a pointer to a CREATESTRUCT			LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;						// That CREATESTRUCT contains the LPVOID parameter passed to CreateWindowEx			// which was a casted MyWindowData pointer			MyWindowData *myWindowData = (MyWindowData*)lpcs->lpCreateParams;						// Store this pointer as user-data on the window-handle			SetWindowLongPtr(hWnd, GWLP_USERDATA, (ULONG_PTR)myWindowData);		} break;				// Window destroyed		case WM_DESTROY:			PostQuitMessage(0);		return 0;				// Key pressed		case WM_KEYDOWN: {			// Retrieve the pointer stored as user-data for the window-handle			MyWindowData *myWindowData = (MyWindowData*)GetWindowLongPtr(hWnd, GWLP_USERDATA);						switch(wParam) {				case VK_SPACE:					if(myWindowData)						myWindowData->setColor(RGB(rand(), rand(), rand()));				return 0;								case VK_ESCAPE:					DestroyWindow(hWnd);				return 0;			}		} break;				// Last message ever sent to a window		case WM_NCDESTROY: {			// Retrieve the pointer stored as user-data for the window-handle			MyWindowData *myWindowData = (MyWindowData*)GetWindowLongPtr(hWnd, GWLP_USERDATA);						// Delete the window-data, as it can never again be retrieved from the window-handle			// which ceases to exist			delete myWindowData;		} return 0;	}		return DefWindowProc(hWnd, msg, wParam, lParam);}
thanks a lot. the code brought me up with an idea that should have come to my mind a lot earlier ^^. it kinda cleared the fog and now everything is clear :D

This topic is closed to new replies.

Advertisement