Window doesn't recover after regaining focus

Started by
4 comments, last by Buckeye 15 years, 9 months ago
Hello everyone, I'm fairly new to game programming. I'm currently having an issue with my game window. When I first run the program all input works. However when the window loses focus (alt+tab, etc) does window doesn't seem to recover properly. The game window comes back up, but no input is accepted. I tested my game loop as well as some other functions. I think i narrowed down the issue to Key_Down(int) and/or Poll_Keyboard(). It seems that no information is passed to this two functions when the window regains focus. Anyone has any idea why this might be? I'm not sure what piece of code to post here: void Poll_Keyboard() { dikeyboard->GetDeviceState(sizeof(keys), (LPVOID)&keys); } int Key_Down(int key) { return (keys[key] & 0x80); } edit: Forgot to put a title =) [Edited by - roloenusa on June 27, 2008 1:33:38 PM]
Advertisement
If you don't already, you need to trap WM_KILLFOCUS and WM_SETFOCUS. KillFocus should set a flag or otherwise stop I/O processing. SetFocus should restore processing.

When your window loses focus, it loses user input so there's no sense polling input it shouldn't be receiving. Depending on what your program does when it's active, you may want to suspend all activity (except for WM_PAINT, which should just Present the last frontbuffer and nothing else).

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

This isn't necessarily related to your problem here, but make sure you're also set up to recover from a lost device. There's detailed info on how to do that over in the documentation.
Quote:make sure you're also set up to recover from a lost device

Absolutely! If you trap WM_KILLFOCUS and suspend activity, then the first DX-related activity to do on WM_SETFOCUS is to check the device status.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Thank you so much for the prompt responses!

I apologize, i'm fairly new to DirectX and game programming. I set up a case under my winproc function. Is this correct? It seems to work perfectly as per my testing!

Now, i only set WM_SETFOCUS as follows:

case WM_SETFOCUS:
static bool init_Setfocus = 0; //false= Initialize with the proper functions
//true= get the keyboard and mouse back

if (init_Setfocus != 0)
{
if(!Init_Keyboard(hWnd))
MessageBox(hWnd, "Error initializing the keyboard", "Error", MB_OK);
if(!Init_Mouse(hWnd))
MessageBox(hWnd, "Error initializing the mouse", "Error", MB_OK);
}

init_Setfocus = true;
return 0;

This works and serves the purpose for now i guess. At least until i learn a better way to handle things.

Now, is it necessary to set up WM_KILLFOCUS as well? is it just a responsible thing to do, or only if it's require by the gameplay? What should be included in WM_KILLFOCUS? i imagine just the release the device statements.
Sorry, the "device" we were referring to is the IDirect3DDevice9 (or whatever version of DX you're using). Your application should have routines to be called when the D3D device is lost and when it is reset, perhaps named OnDeviceLost() and OnDeviceReset().

Each loop through your application's run code should test for a lost device before the device is used for anything, perhaps using something like
pDevice->TestCooperativeLevel();

One of the reasons for trapping WM_KILLFOCUS and suspending activity is that another application may cause your device to be lost. If you continue running when the device has been lost, the result will be indeterminate.

Another reason for trapping WM_KILLFOCUS and suspending activity is that the user has implicitly stated that it's not your application s/he wants to be using at the moment. Out of courtesy, you should stop what you're doing until the user returns attention to your app![smile] If you don't suspend activity and you have a proper run loop, testing for a lost device, your code could reset your device, causing the other application's device to be lost, causing your app to reset, etc. That's just not good practice.

If you have a proper run loop, WM_SETFOCUS isn't as important as WM_KILLFOCUS. If setfocus resumes activity, then the run loop will take care of "discovering" the lost device and doing the proper recovery. That recovery would include checking the keyboard device, etc.

Suggestion: if you're not too invested in DInput (actually, even if you are), don't use it. Use the normal windows messaging system to get input from the user (WM_CHAR, WM_KEYDOWN, WM_KEYUP, WM_MBUTTONDOWN, etc.). That will be plenty fast enough in the vast majority of cases.

That will also take care of a loss of focus as your window won't receive character input.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

This topic is closed to new replies.

Advertisement