Jump to content
  • Advertisement
Sign in to follow this  
miggs

confused with peekmessage and looping

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

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

Share this post


Link to post
Share on other sites
Advertisement
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;
...

?

Share this post


Link to post
Share on other sites
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()?

Share this post


Link to post
Share on other sites
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. :/

Share this post


Link to post
Share on other sites
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 variable
COLORREF g_color;

// Main
int 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 you
LRESULT 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);
}

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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 window
class MyWindowData {
public:
void setColor(COLORREF color) {
m_color = color;
}

COLORREF getColor() {
return m_color;
}

private:
COLORREF m_color;
};

// Main
int 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 you
LRESULT 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);
}

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!