# Run game loop while window is dragged?

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

## Recommended Posts

I'm trying to get an application to continue rendering and running even while the user is dragging the window. I've read some stuff about it, and the only methods I've heard that might be feasible are to listen to windows messages through hooks and continue running the application that way. To be honest I'm not a big Windows programmer, I'm more of a gameplay programmer (cameras, controls, combat, etc....) so some of the .NET stuff is a bit confusing still. Does anyone have a small demo or snippet of code that demostrates how to continue a normal game loop while a window is being dragged?

##### Share on other sites
This is a frequently asked question on the boards. Please use the search function.

Summary of the FAQ:

Many messages and events are intercepted while a window is being resized or dragged. There are some pretty good reasons for that behavior, and you need to know the low-level stuff if before you mess with it.

One of the easiest solutions is just have your application use a timer, with the timer's function to run your main update loop. For a regular Windows application, you should either use a system timer as above or a high frequency waitable event. Sorry, no code snippets, I'll leave that as an exercise for the search engines.

##### Share on other sites
I've spent the last 8 hours on search engines. I've found no demos or snippets of this occuring.

I also searched through the forums here and found threads on this same topic, they did not result in any answers, just links to other threads with others asking the same thing.

I agree there are likely good reasons why this occurs, nevertheless the game I'm working on needs to run while the window is moving, just like games like World of Warcraft.

I am willing to learn the low-level reasons why this occurs. It just seems like noone has the complete answer or solution to this, and the MSDN sources give seemingly partial/incomplete explanations and examples that are missing most of the source so you're just left with more questions about what might be missing.

##### Share on other sites
Ok, I've got a callback timer calling my main loop, and it works. Thanks for the tip.

Seems to me that this callback timer would get called all the time no matter what, is there anything I should be worried about?

Also, I have to set the timer update time. If I set it really low, like something ridiculous like 1ms, and the system can only run at 5ms, will I only get a call to the timer after 5ms? Furthermore, if I set it to something more reasonable, like 10ms, and the system is fluctuating between 5-20ms, what will happen?

For example (10ms timer):
5ms passes
5ms passes - timer fires
5ms passes
15ms passes - timer fires once?

##### Share on other sites
The GoogleFu is weak with you. [grin]

Clicky
Clicky
Clicky
Clicky

There are many more, but those look most relevant.

##### Share on other sites
Quote:
 Original post by lordikonIf I set it really low, like something ridiculous like 1ms, and the system can only run at 5ms, will I only get a call to the timer after 5ms? Furthermore, if I set it to something more reasonable, like 10ms, and the system is fluctuating between 5-20ms, what will happen?
It all depends on how Windows schedules your app.

You should write your code to be tolerant of skipped frames and bad OS scheduling. You never know when another process will cause yours to stall.

You said you are more focused on the gameplay rather than the main engine, and these are engine details. If your simulation is running behind, you need to run the simulation's update multiple times. Rendering, on the other hand, should be decoupled from the simulation update and be run as frequently as possible. If you want to be able to render more frequently than your timer allows, you will need to do additional processing that your post implied you would rather avoid.

##### Share on other sites
A Timer isn't very reliable for that exact reason. When your application loses control of the thread, like in a Sleep(time) operation, what you're telling windows is to return control to you after a MINIMUM of time has passes - if more time passes, that's your loss.

The same is true with a timer. If your application doesn't recieve control in time, you really can't do anything about it. The smart thing to do would be to make all of your updates (well, most of them) time dependent, and when you perform their respective updates, use the change in time since the last update.

Instead of using a timer, why don't you use the typical game loop? Which is something like this:

MSG mMessage;
DWORD dStartTime = GetTickCount();
DWORD dLastTime = dStartTime - 25;
DWORD dUpdateTime = dStartTime;
while (1)
{
if( PeekMessage( &mMessage, 0, 0, 0, PM_REMOVE ) )
{
if( mMessage.message == WM_QUIT )
{
break;
}
TranslateMessage( &mMessage );
DispatchMessage( &mMessage );
}

while( (dStartTime = GetTickCount()) - dLastTime < 25 );
dLastTime = dStartTime;

Update( dLastTime - (dUpdateTime = GetTickCount()) );
RenderFrame();
}

Of course, this is just an example, and it's not very effective. There can be errors of up to a few milliseconds, but atleast your app will still be updating, no matter what.

I use the same logic, but with a very accurate timer that I built to do pretty much the same thing, but with ~4 nanoseconds precision.

##### Share on other sites
Within the timer callback I can use GetTickCount to get a very accurate time delta over the course of a frame, that isn't the issue. What I'm wondering is if I will get calls to the program less frequently than if I were not using a timer callback. Either way my timedelta would be accurate, but if I'm getting a lower framerate through a timer callback then I might have to find a better way to do this.

Additionally, I see no reason to use the timer callback except in the condition where a the window title bar is being used to move the window, that is the entire reason I started this endeavor. Would it make sense to register for a callback only once the window title bar is being used to move the window?

Anyway, thanks for the help guys, I'll let you know how it all goes once I get it into the game itself, right now I'm just using a very simple 3D program to test with.

##### Share on other sites
frob, the 3rd link was the winner. Works like a charm, and only uses timers when the window is being moved around. Of course, I will do a variant of this and rather than start the timer on WM_ENTERSIZEMOVE, I will do it on WM_SYSCOMMAND and use the wparam (SC_MOVE + HT_CAPTION) which will occur only when the title bar is used to move the window.

But now that I think of it, I still want the game to update during a size change, just not rendering.

Thanks again.

##### Share on other sites
Not really. It seems like you're worried about the user doing something that bombards windows with messages, therby preventing you from updating or rendering. Dragging the window is only one of several ways for that to happen. Therefore, the timer callback should either always be utilized, or never. Conceptually, it's just ugly to have to monitor 20 different messages and set your callback function and timer appropriately.

But to answer your question, yes, with the callback function mechanism, you are getting less control than through other methods.

You said "normal game loop" in your first message - is there anything keeping you from going fullscreen and getting rid of that problem?

##### Share on other sites
It is a casual PC game, so we don't want to force fullscreen on the user. Fullscreen will indeed be the default, but you want to support all major options to satisfy the customer....I guess. :)

I agree that a single method for game updating would be great, but if timer callbacks are slower then I'd prefer to only use them when necessary.

##### Share on other sites
Quote:
 Original post by Brain meNot really. It seems like you're worried about the user doing something that bombards windows with messages, therby preventing you from updating or rendering. Dragging the window is only one of several ways for that to happen. Therefore, the timer callback should either always be utilized, or never.

That's not why your app stops running when the use starts moving/resizing it. It's because Windows enters a modal dialog loop. The same would happen if you called MessageBox to pop up a message box - a modal message loop is entered and your "normal" loop stops running.

Registering a timer gets around it because WM_TIMER still gets passed to your WndProc even in the modal dialog loop.

Quote:
 Original post by lordikonI agree that a single method for game updating would be great, but if timer callbacks are slower then I'd prefer to only use them when necessary.

Yeah, it probably wouldn't run at 100% speed, but you can get it pretty close. I think using WM_TIMER for windowed mode is not a bad idea, but I guess it just needs some experimentation...

##### Share on other sites
Don't know how well it works with DirectX, but with OpenGL, running the game loop including all rendering in a thread other than the one owning the window is not particularly painful. It seems much less of a nightmare as many people seem to think (or I'm missing something?).

The only downside is that you have to re-post the relevant messages (keypresses, mouse clicks, etc.) from one thread to another, but that's not so much of a problem, really.
For some reason, I was unable to get Windows to create a message queue for the other thread (as in "simply call any GDI function" or as in "create a message-only window"), but it's no biggie to implement something custom...

Essentially the code (the relevant bits) that I'm using looks like this:
int WINAPI WinMain(...){	RegisterClassEx(...);	auto_handle<HWND> hwnd = CreateWindow(...);	RenderThread renderthread(hwnd);	renderthread.Run();	ShowWindow(hwnd, nCmdShow);	MSG msg;	while(GetMessage(&msg, NULL, 0, 0))	{		TranslateMessage(&msg);		DispatchMessage(&msg);	}	renderthread.PostMessage(Message(WM_QUIT));	renderthread.Join();	return 0;}void RenderThread::Entry(){	try	{		OpenGL opengl(hwnd); // context creation and cleanup etc.		...		Message* msg;		do		{			...			while((msg = msgq.Read()))				HandleMessage(msg);		}while(running);	}	catch(int ex) // if an exception made it here, it's rather bad	{		SendMessage(hwnd, WM_UNHANDLED_EXCEPTION, ex, 0);		SendMessage(hwnd, WM_CLOSE, 0, 0);	}}
So far, I've not encountered any kind of problem with that approach. It runs on nicely while you drag the window or while the system menu is open, and it doesn't crash and burn. It should hopefully be more or less leak- and exception-safe too.

##### Share on other sites
A little off topic, but that GetTickCount() loop Brain Me suggested is horrific - it's by no means a "typical game loop", it's just the really crap one that directxtutorial.com uses.

1. It's a busy loop - you're using up 100% of the CPU doing absolutely nothing, which will starve other processes of CPU time, and be bad for mobile CPUs like you have on laptops - they'll run at full speed when they don't need to.
2. GetTickCount() is very inaccurate. On my Vista machine, it's only accurate to 16ms - mesuring a 25ms period with a timer accurate to 16ms is 64% margin of error, which is extremely high.
3. You're only reading a single window message before processing one game tick. That's a very good way to cause your window message queue to overflow quickly, cause your app to get gradually less and less responsive, and possibly eventually crash (I don't actually know what happens if you have too many messages in the queue).

##### Share on other sites
I won't have to worry about GetTickCount() because our game is using third-party software for performance monitoring, which includes an accurate timer to give us a time delta. However, I'm guessing you'd want to use QueryPerformanceCounter to get an accurate snapshot of the time.

##### Share on other sites
Quote:
 Original post by samothDon't know how well it works with DirectX, but with OpenGL, running the game loop including all rendering in a thread other than the one owning the window is not particularly painful.

You can't do this with Direct3D. Direct3D needs to be used on the same thread that created the window.

Quote:
 Original post by samothThe only downside is that you have to re-post the relevant messages (keypresses, mouse clicks, etc.) from one thread to another, but that's not so much of a problem, really.For some reason, I was unable to get Windows to create a message queue for the other thread (as in "simply call any GDI function" or as in "create a message-only window"), but it's no biggie to implement something custom...

If you want to create a message queue for a thread, all you have to do is call GetMessage or PeekMessage and the queue will be "automagically" created for you. However unless your other thread has a window, you'll have to use PostThreadMessage to send messages to that thread.

##### Share on other sites
It's just like to note that GetTickCount() is the devil. Use QueryPerformanceCounter().

##### Share on other sites
Quote:
 Original post by MJPIf you want to create a message queue for a thread, all you have to do is call GetMessage or PeekMessage and the queue will be "automagically" created for you. However unless your other thread has a window, you'll have to use PostThreadMessage to send messages to that thread.
Yes, but that still won't work, at least not without jumping through a few hoops, if you want your application to be able to run on non-Vista Windows, too. This is a bit far off-topic i.r.t. the OP, though.
If it's of interest, I can of course elaborate, but seeing that implementing your own message queue (which works without any problems) is a dozen lines of code, it's probably not of much interest.

##### Share on other sites
Quote:
Original post by samoth
Quote:
 Original post by MJPIf you want to create a message queue for a thread, all you have to do is call GetMessage or PeekMessage and the queue will be "automagically" created for you. However unless your other thread has a window, you'll have to use PostThreadMessage to send messages to that thread.
Yes, but that still won't work, at least not without jumping through a few hoops, if you want your application to be able to run on non-Vista Windows, too. This is a bit far off-topic i.r.t. the OP, though.
If it's of interest, I can of course elaborate, but seeing that implementing your own message queue (which works without any problems) is a dozen lines of code, it's probably not of much interest.

I assure you it works...I've used it plenty. What problems did you encounter?