Archived

This topic is now archived and is closed to further replies.

serratemplar

this question cannot be answered: alt-tab

Recommended Posts

serratemplar    1656
This question has been asked a million times on this site, and I feel that I''ve read thru all of those posts, I''ve even posted this question, and nobody every answers it. I am beginning to believe that the answer to this question is protected by some super secret all powerful illuminati-style cult, and I am very, very sad about this. People have found ways to disable alt-tab, and people allude to "lpDirectDrawObj->RestoreAllSurfaces" and, well...here is my deal. When someone alt-tabs out of my application, my app closes. Poof. Gone. As if it had not been running. What *really* irks me is that before I upgraded my processor and reformatted, my code worked fine. I''ve got this in my message handler: case WM_ACTIVATE: { if (LOWORD(wparam)==WA_INACTIVE) g_App.SetWindowStatus(false); if (LOWORD(wparam)!=WA_INACTIVE) { g_App.SetWindowStatus(true); g_App.RestoreSurfaces(); } } break; SetWindowStatus tells my application to hold its horses. This is only a skeleton initializing directdraw7, so it''s not doing anything fancy at all. I have a primary surface and a backbuffer. That''s it. It''s a fullscreen, exclusive app, which I draw on a fullscreen popup window (the norm). When the user tabs out, my window loses focus and should minimize. Instead it closes. It disappears from the taskbar and from the taskmanager. You cannot alt-tab back in: it is gone. People must hate this question, because the only people who answer it nowadays seem to be people who are content to disable it, and if professional game companies can do it (even the really BAD ones) then it''s gotta be doable. Even if you swore you''d never answer it again, if anybody can help me to get alt-tab working in my game(s) I promise I will answer this question for everyone for the rest of my programming life. Open me an Alt-Tab board on this site and I will moderate it, I will answer the question again and again as pennance for all time that remains for this Earth. Please, please, please someone help me. It makes me tear my hair out not knowing how. Thank you for reading, even if you didn''t answer, Steve By the way, please don''t post how to disable ALT-TAB here. Thanks to the hundred other forum posts, I could do that.

Share this post


Link to post
Share on other sites
izzo    437
That''s very odd, are you sure your window status flag isn''t causing your message loop to exit? In response to the inactive message you should probably call ShowWindow(hWnd, SW_MINIMIZE). Hmm, also, you aren''t returning true in that code snippet; you should return true from your window procedure if you handle the message. Unless you''re doing that elsewhere in your message procedure.

I wouldn''t be content to disable alt-tab; in fact most people say that you should not disable it. I usually don''t bother handling it (although that was when I was using OpenGL; everything seemed to work there. Now that I''ve moved over to D3D I guess I''ll have to think about this issue soon too).

cheers
sam

Share this post


Link to post
Share on other sites
serratemplar    1656
I can''t believe it. =)

I don''t know whether to feel relieved or colossally stupid. I had my main program loop based on the WindowStatus, which set to false on a tab out, so of course my program exitted.

After making the main loop dependent on only a WM_QUIT or WM_DESTROY msg, I have found that I can in fact tab in and out.

Simple insights.

Well, thanks to anyone who pondered this, and - as I promised - I will answer ALT-TAB questions from now on. =)

Please don''t give me a forum.

Share this post


Link to post
Share on other sites
serratemplar    1656
I take it back

It doesn''t work reliably. Worked the very first time, now I can''t tab back in, but it still seems to be running (it''s in the taskbar)

Any further ideas?

Share this post


Link to post
Share on other sites
serratemplar    1656
Okay, this is not an answer but the problem is this:

while(m_lpddsPrimarySurface->Flip(NULL, DDFLIP_WAIT)!=DD_OK);

Once this operation has taken place (a page flip), alt-tab will not restore the application. You can tab out but not back in...it won't remaximize. I have to use the task manager to kill it. *Maybe* it's stuck in that loop?? But that loop has always worked for me before...

My attempt to recover is this:

ShowWindow(m_hWindow, SW_RESTORE);

if (m_DirectDrawObject)
if (m_lpddsPrimarySurface->IsLost())
m_DirectDrawObject->RestoreAllSurfaces();

You can still tab between the game and everything else that's running...it just won't restore itself, won't redraw itself, etc. Button on taskbar depresses as if it should though.

[edited by - serratemplar on May 26, 2004 1:12:56 AM]

Share this post


Link to post
Share on other sites
izzo    437
What exactly do RestoreSurfaces() and RestoreAllSurfaces() do? From what I understand, you need to re-create everything: vertex buffers, textures, devices. Check out this MSDN link (it actually says it''s archived content so there''s probably a newer up-to-date version somewhere). Also here is a sample that I found from a cursory google search that might help.

cheers
sam

Share this post


Link to post
Share on other sites
serratemplar    1656
RestoreAllSurfaces is a member of IDirectDraw7, RestoreSurfaces is a member of my own application object that kicks in when the user alt-tabs back into my program.

Share this post


Link to post
Share on other sites
marcus12024    162
Not sure if this''ll help you, but here''s what I''m doing in my WndProc function. I had a hell of a time getting this working at first, too - but when I finally figured it out it was all worth it. I can minimize, maximize, alt-tab in and out, from both windowed and full-screen, in any of the available resolutions. So it is possible.

If you need to see any of the functions, just let me know.

		case WM_ACTIVATE:
{
static bool reCreateAll = false;

if (LOWORD(wParam)==WA_INACTIVE) {
// the user is now working with another app

gameRunning = false;
gameTimer.OnLoseFocus();

if (!graphics.Windowed()) { // we were in full-screen, when we get re-activated

// we''re going to have to reset device


reCreateAll = true;
}

} else {
// the user has now switched back to our app


if (reCreateAll) { // we had switched to Windows from full-screen, need to recreate device and resources

ReleaseResources();
// release all resources first --> sprites, textures, fonts

graphics.Reset();
// now restore all resources

RestoreResources();

}

gameRunning = true;
gameTimer.OnRegainFocus();

}

Share this post


Link to post
Share on other sites
AhmedSaleh    190
Hi,
you could consider your Applications as a screen saver , hence we cant use ALt-tab keys by using this function
SystemParametersInfo(SPI_SCREENSAVERRUNNING, TRUE, NULL, 0);

there is an article in Game Programming Gems II book , about ALT-TAB problems named ( Linear Programming ) .


Ahmed Saleh



Share this post


Link to post
Share on other sites
TravisWells    276
quote:
Original post by AhmedSaleh
SystemParametersInfo(SPI_SCREENSAVERRUNNING, TRUE, NULL, 0);



Please don''t do this. If you have to crash when the user Alt-Tabs, then fine, crash. Don''t disable parts of the OS because of bugs in your program.
Disabling it will just annoy your users. (And I''m pretty sure that it won''t work on NT-based windows)

Share this post


Link to post
Share on other sites
serratemplar    1656
I really appreciate that you''ve taken time to offer advice, but in my initial post I did ask that no one suggest how to disable Alt-Tab. It is my goal to master it! I''d feel like a chump if I didn''t. =)

Share this post


Link to post
Share on other sites
serratemplar    1656
Okay, this is what I''ve got for my message handler...


case WM_ACTIVATE:
{
switch (LOWORD(wparam))
{
case WA_ACTIVE: // fall thru to next one; either way our prog has regained focus

case WA_CLICKACTIVE:
{
if ((HWND)lparam==g_App.GetWindowHandle())
{
g_App.SetWindowStatus(true);
g_App.DDRestoreSurfaces();
}

} break;

case WA_INACTIVE: // our prog has lost focus

{ g_App.SetWindowStatus(false);
} break;

} // end switch (LOWORD(wparam))


} break;


Tabbing back in still doesn''t work, but now I suspect it has to do with my graphics engine, which isn''t working anyway...so something might be tripping it up in there. Makes me sad.

Thanks for everyone''s help. If anyone sees anything inherently wrong with the code I posted, please say so...otherwise I''ll presume (For now) that it''s workable and I''ll try to debug my graphics engine.

That''s what I get for trying to rework my old shell program. =)

Share this post


Link to post
Share on other sites
kVandaele    138
doesn''t DX7 have a TestCooperativeLevel?
HRESULT hr = pD3DDevice->TestCooperativeLevel()
if(D3DERR_DEVICELOST == hr){
// pause the game... or really, do nothing
}else if(D3DERR_DEVICENOTRESET == hr){
// release all graphical devices: sprites, textures, vertexbuffers, ... see the sdk help
// reset the device
// reinitialise your sprites, textures, ...
}else{//D3D_OK
//query keyboard/mouse (DI)
Render();
}

After that just make sure your WinProc handles the window reactivation message with "return DefWindowProc(hWnd, msg, wParam, lParam);"

Share this post


Link to post
Share on other sites
alnite    3438
quote:
Original post by serratemplar
Okay, this is not an answer but the problem is this:

while(m_lpddsPrimarySurface->Flip(NULL, DDFLIP_WAIT)!=DD_OK);

Once this operation has taken place (a page flip), alt-tab will not restore the application. You can tab out but not back in...it won''t remaximize. I have to use the task manager to kill it. *Maybe* it''s stuck in that loop?? But that loop has always worked for me before...

To me, that sounds so much like a surface lost problem. Or if you are using DirectInput or DirectSound, it might be from one of their lost devices/buffers.

This is what I suspect. Application runs fine. You tab out, it minimizes. You tab back in, it exits or freezes. DirectX might be trying to access an unrestored surface/device/buffer, and it failed. Maybe somewhere you originally handled this failure by exiting the program. That''s why when you tabbed back in, it exited.

Now you have made some modifications in your code, instead of handling the error by exiting, you proceed. But since the lost surface/buffer/device hasn''t been restored yet, DirectDraw can''t flip the surface, therefore your application freezes.

Share this post


Link to post
Share on other sites
Hyatus    122
I''m at work and don''t have the documentation in front of me, but
I believe you do something like this:

if(DDrawPrimSurface == DDPS->IsLost())
{
RestoreSurface();
}
DDraw->Flip();

I''ll check the actual code when I get home if someone doesn''t
answer better before then.

-Hyatus
"da da da"

Share this post


Link to post
Share on other sites
serratemplar    1656
So, do you think IDirectDraw7::RestoreAllSurfaces isn''t doing it''s job correctly?

Here''s something *really* weird. I switched my message handler to this:


case WM_ACTIVATEAPP:
{
if (wparam) // this app is being activated

{
g_App.SetWindowStatus(true);
g_App.DDRestoreSurfaces();
}
else
g_App.SetWindowStatus(false);

} break; // end case WM_ACTIVATEAPP



And now if I tab it, it automatically tabs back in, and the bottom eighth or so of my background surface is all garbled!

At least I can tab back in (whether or not I want to, it does), so that''s sort of progress. =)

Share this post


Link to post
Share on other sites
serratemplar    1656
SUCCESS!!!!!

Alright. =) I fixed it. Here''s what I did....

First of all, I had a misplaced ShowWindow call, which was causing the application to "automatically tab back in", as I said. That was silliness on my part. The real lesson is this:

Instead of using WM_ACTIVATE, I found WM_ACTIVATEAPP on www.msdn.com. (Way I found this was by looking up IDirectDraw7::TestCooperativeLevel, which turned out to be unnecessary for my purposes.) Here''s my new message handler branch:


case WM_ACTIVATEAPP:
{

if (wparam) // this app is being activated

{
g_App.SetWindowStatus(true);
g_App.DDRestoreSurfaces();
}
else
g_App.SetWindowStatus(false);

} break; // end case WM_ACTIVATEAPP



IDirectDraw7->RestoreAllSurfaces() seemed to work, but to be thorough I decided to play it like a D3D coder and check them all manually instead. Also, what was making my background screwy was that when the user tabbed out, I was restoring my surface but (guess what) not reloading my bitmap, which was in video ram. So I had to reload that, thus


void CApplication::DDRestoreSurfaces(void)
{

if (m_DirectDrawObject)
{

if (m_lpddsPrimarySurface->IsLost())
m_lpddsPrimarySurface->Restore();

if (m_lpddsBackBuffer->IsLost())
m_lpddsBackBuffer->Restore();

// now reload surfaces in videoram


if (m_lpddsBackgroundImage->IsLost())
{
m_lpddsBackgroundImage->Restore();
DDReLoadBitmap(m_lpddsBackgroundImage, "tetris1.bmp");
}

} // end restore if-block


} // CApplication::DDRestoreSurfaces



DDLoadBitmap and DDReloadBitmap are DirectDraw utility functions found in ddutil.cpp...you''ve gotta dig it out of your directx sdk and manually link it in to your project. (Or you can copy and paste the code if you wish.)

Anyway, it works 100% now =) so thanks everyone for the help.

Share this post


Link to post
Share on other sites
izzo    437
Thanks for posting your solution! I''m going to bookmark this thread for future reference :-)

sam

Share this post


Link to post
Share on other sites