Restoring desktop resolution during alt+tab

Many many questions today

I’m trying to restore the desktop resolution when my app is fullscreen and the user presses alt+tab. I’m trying to do this with this code:

m_dmSaved contains saved video mode from window creation…

void GLWindow::Activate(bool bActive)
{
if( bActive )
{
// change back to game res
if( m_bFullScreen )
{
DEVMODE dmScreenSettings;
memset( &dmScreenSettings, 0, sizeof(dmScreenSettings) );
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = m_iWidth;
dmScreenSettings.dmPelsHeight = m_iHeight;
dmScreenSettings.dmBitsPerPel = m_iBpp;
dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

        if( DISP_CHANGE_SUCCESSFUL != ChangeDisplaySettings( &dmScreenSettings, CDS_FULLSCREEN ) )
        {
            MessageBox( NULL, "Unable to switch back into game video mode!", "Error", MB_OK | MB_ICONSTOP );
            PostQuitMessage( 0 );
            return;
        }
        ShowCursor( FALSE );
    }

    wglMakeCurrent( m_hDC, m_hRC );
}
else
{
    wglMakeCurrent( NULL, NULL );

    // change back to regular desktop
    if( m_bFullScreen )
    {
        if( !ChangeDisplaySettings( NULL, CDS_TEST ) )
        {
            ChangeDisplaySettings( NULL, CDS_RESET );
            ChangeDisplaySettings( &m_dmSaved, CDS_RESET );
        }
        else
        {
            ChangeDisplaySettings( NULL, CDS_RESET );
        }
        ShowCursor( TRUE );
    }
}

}

I’ve tried calling this from both WM_ACTIVATE and WM_ACTIVATEAPP to no avail. Any ideas? I know I’ve just gotta be doing something wrong. Thanks in advance!

I confess I didn’t read through your code, but AFAIK, all you need to do to restore the desktop mode is this:

ChangeDisplaySettings(NULL,0);

As to the messages, WM_ACTIVATEAPP should do the trick. Note that the message for activation can be either WA_ACTIVE or WA_CLICKACTIVE.

      • MUPPET NEWS FLASH * * *

I actually went ahead and tested this. I only tested alt-tabbing OUT of the program, but alt-tabbing back in should work too. Here’s the code:

// inside WndProc( )
// …

switch (uMsg) {
// … other messages, etc.

case WM_ACTIVATEAPP:
{
    if (LOWORD(wParam) == WA_INACTIVE)
        ChangeDisplaySettings(NULL,0);

    // add other cases, WA_ACTIVE and WA_ACTIVECLICK here

}

//  ... other messages, etc.

}


Rui del-Negro
delnegro@netcabo.pt

[This message has been edited by delnegro (edited 03-16-2001).]

Ok, I switched it to use ChangeDisplaySettings( NULL, 0 ) and now it switches back to the desktop perfectly. However when I switch back into the application nothing shows up (black screen) at the same time my framerate drops in half. Any ideas? If the full source would help I’d be happy to send it

You have to reload all textures and other data wich is loaded into video memory when switching back to your game.

Well, thats all good, but I’m drawing a single red quad centered at the origin, to textures, no data, just a hand built quad…

Well, I’m not exactly a hardened OpenGL guru (in fact I’m still at the “hello world” stage ), but I looked into a couple of programs (namely NeHe’s tutorials) and I noticed that, everytime he switches from fullscreen to windowed, he destroys everything (device context, rendering context, and even the main window), switches mode and then creates everything again. I don’t know if this is absolutely necessary, or if only some of these steps are necessary. (any hardened gurus out there? ).

If you’re already doing this in your program, I don’t know what else to suggest, if not, try it and see if it fixes the problem.

If you need the full code you can get it nehe.gamedev.net (or, more precisely, at http://nehe.gamedev.net/tutorials/lesson01.asp ).

Hope it helps.


Rui del-Negro
delnegro@netcabo.pt

[This message has been edited by delnegro (edited 03-16-2001).]

Thanks for you reply Delnegro, NeHe is where I started and he doesnt properly support the alt+tab thing either. I’m at my wits end with this stuff… grr…

I didn’t say he did. But there’s enough information even on the first tutorial to do what you want. Namely:

  1. It shows how to restore the desktop video mode
  2. It shows how to switch between windowed mode and fullscreen

The only other thing you need to know is how to detect if Alt+Tab has been pressed (which you already do - listen for WM_ACTIVATEAPP messages).

So what you need to do is this:

If your program has received a WA_INACTIVE in WM_ACTIVATEAPP while in fullscreen:

  • Destroy everything (RC, DC, and program window), as shown in the NeHe tutorial for when the program switches from full-screen to windowed.
  • Switch to the desktop mode using (NULL,0) (also in the tutorial)
  • Optionally, create a new window for the program (you may want to create a minimized window, if the program is only meant to run in fullscreen), and re-create the RC, DC, etc. if you want to continue to use OpenGL in windowed mode.

If your program was inactive and received a WA_ACTIVE or WA_ACTIVECLICK in WM_ACTIVATEAPP:

  • Destroy the RC, DC, etc. and the window (this is in the NeHe tutorial).
  • Switch to the mode you want (again, covered in the tutorial).
  • Re-create the window and the contexts (also in the tutorial).

So all you need to do is use the code that the tutorial uses for when F1 is pressed and adapt it to run when your program receives a WM_ACTIVATEAPP message. What happens when people switch to the desktop is up to you (ie, keep the program running in a window or minimize it), but the rest is all in the tutorial, you just need to adapt it.


Rui del-Negro
delnegro@netcabo.pt

[This message has been edited by delnegro (edited 03-17-2001).]

Do you really think its necessary to destroy everything just when alt+tabbing out? I certainly dont, John Carmack certainly doesnt (quake 3 doesnt destroy everything and reload every time you alt+tab). That processes would potentially waste ALOT of time. I’ll just stick to not using alt+tab until I figure out the correct way.

For my two cents, I would destroy everything when switching back to the desktop. Why? Because the user might also be running some other GL program and to be friendly to it, you should release the GL resources when they are not being actively used. The delay is worth it in the end. Better to have multiple GL programs coexist peacefully rather than have one do god knows what.

[This message has been edited by DFrey (edited 03-17-2001).]

For fullscreen games, maybe. For windowed GL apps, the full delete-rebuild seems extreme; it could conceivably impose a delay of several seconds on the user just for switching focus between apps.

I would think that recreating the lot is only necessary when the screenmode has changed, but that’s just a guess.

To BwB:

Well, you only run that code when you switch from fullscreen to windowed or minimized mode (to display the desktop). Do you want your program to keep running? Probably not, right? So who cares about the time it takes (anyway, it doesn’t take that long; no more than 1 second, and that’s because of the video mode change and the time the monitor takes to adapt).

As I said, I don’t know if you need to destroy everything. You tried switching without destroying anything and you say it slowed your program down. NeHe destroys everything when he switches from the desktop to fullscreen or vice-versa, and it seems that it works.

And note that “everything” means the Rendering Context, the Device Context and the window. It doesn’t mean the program or the data. Quake wouldn’t need to “reload” anything, simply to release the handles before changing mode and re-acquire them after the mode change is successful.

And why does everyone have to mention what John Carmack thinks, in these forums…?!

To DFrey:

In my experience, you can run two OpenGL programs at the same time, but they tend to run much slower, so I fully agree: if a program was designed to run in fullscreen, I would deactivate it when the user presses alt+tab to go to the desktop (just create a minimized window that, when activated, goes back to fullscreen mode).

To MikeC:

If you read the previous messags in the thread you’ll see that was the case: we’re talking about switching from fullscreen (and possibly in a different video mode) to the desktop and back. Programs don’t even need to handle simple alt+tabbing between windowed programs; Windows takes care of that.


Rui del-Negro
delnegro@netcabo.pt

[This message has been edited by delnegro (edited 03-18-2001).]

Originally posted by delnegro:
And why does everyone have to mention what John Carmack thinks, in these forums…?!

Because he’s been there and done that and already knows the answer to the question!

Thats for the clarifications, I’ll look into releasing and restoring stuff but I’m certainly not going to destroy the window I find that counter productive

Well… about the alt-tab problem, when the user wants to switch out of my game, or try to use windowed mode, I just change the video mode to the desktop, the window properties, and that’s it.

When the user switch back to fullscreen, I change the video mode, the window properties, and reload everything that used vidmem (textures & VAR mem).
I don’t have any problem at all with this method…

What nehe is doing (releasing everything, including the render context, and even the main window!!) seems very unnecesary to me, and doing that, you’ll also have to restart DirectSound and other APIs using the main window handler (hwnd).

  • Royconejo.

Well, BwB said that when he tried simply changing the video mode, everything slowed down.We’re not just alking about windowed vs. fullscreen, we’re talking about switching to a different video mode. It would be nice if someone who actually .knows. the correct process, and the implications of the incorrect processes would answer. As I said, I’m relatively new to OpenGL, so I don’t know for sure but I think that if you:

  • Switch from a desktop of, say, 800x600x16 to a fullscreen mode of 1024x768x32

…you probably .do. need to recreate the window after switching modes. I’m not sure you can create a window bigger than your desktop (at least most programs won’t let you resize the window beyond the desktop size), so a window created in the desktop mode would be 800x600 at most. Also, when you change the bit depth, you probably need to re-create the contexts. So destroying everything and re-creating may be the safe (right) thing to do.


Rui del-Negro
delnegro@netcabo.pt

In my applications, I separate the actual application data from the rendering context routines so that it is easy just to unallocate video resources (e.g. textures, display lists). But that is for my full screen apps. A windowed app shouldn’t need to do anything but release the DC, wglMakeCurrent( NULL, NULL ). I believe you can still retain your objects this way (Something I need to personally test).

I usually disable alt+tab in full screen mode. That function is not a very good way to leave an openGL app anyway. But, you gotta do what you gotta do, I guess.

I assume the reason NeHe destroys everything is because only one context can exist and be displayed at any one time. You have to destroy it to make a new one.

Funk.

How do you disable alt+tab?

Check the windows message WM_SYSCOMMAND, I think you can use it to disable alt-tab.
Yes, there is few 3D game that can switch on/off smoothly. Even Q3 locks me up from time to time
BTW: Q3 does not change display setting when I switch away from it.

Whenever a ChangeDisplaySettings comes into play it is best really to destroy all and rebuild it all… From my experience it often led to errors if I weren’t doing that.