You don't want to be disabling alt-tab, because it annoys users unnecessarily (like my brother, who's always alt-tabbing out to do other stuff in the middle of his games). The first question: are you using D3D or DirectDraw, because the way to restore stuff is different in each (and I can't say that I've used D3D, so someone else [e.g. Jarrod] will have to fill in the blanks).

In DirectDraw, all surfaces are messed up once you alt-tab and you have to regenerate them. This is easy enough. In addition, any surface that's sitting in video memory must have its picture reloaded because it'll be blanked out.

The trick here is to catch the WM_ACTIVATEAPP message. Windows passed this when your app is activated/deactivated (note that a similar message, WM_ACTIVATE, exists, but you don't deal with that - it handles individual windows in your app getting/losing focus, rather than the main app itself). So... you maintain whether the app has focus. Don't do too much that's hard work if deactivated (no CPU hogging!), minimal drawing if required (maybe, maybe not).

You could handle the WM_ACTIVATEAPP message in a couple of ways -- writing a specific message handler function for it or by catching Application.OnMessage (be careful to not do too much here, since that'll be called for any message that passes through your system).

I won't detail the above since I don't know what system you're using. Instead, I'll go over the general process that I've used and that seems to work (no idea if it doesn't deal with special cases, but never mind.).

Here's the message handling in my WndProc for WM_ACTIVATEAPP:

[pascal][background=#FFFFFF][comment=#0000FF][normal=#000000][number=#C00000][reserved=#000000][string=#00C000] WM_ACTIVATEAPP:
begin
bActive := LongBool(wParam);
Result := 0;

// we have to handle ALT-Tabbing from the user or other ways to lose
// the focus. DirectDraw gets rid of our surfaces when this happens
// so we have to restore them and then reload anything on the bitmaps
// themselves
//
// todo: double-check this works!
if bActive and (DD7 <> nil) then
begin
if g_FullScreen then
begin
DD7.SetCooperativeLevel(Globals.g_Handle, DDSCL_EXCLUSIVE or
DDSCL_FULLSCREEN or
DDSCL_ALLOWREBOOT);
end;

while DD7.TestCooperativeLevel <> DD_OK do
begin
Sleep(0);
end;

ReloadAllImages;
end;

//etc[/pascal]
DD7 is my IDirectDraw7 interface, bActive is a boolean that refers to whether the app's running (side note: I really should eliminate that hungarian notation, sigh), and Globals.g_Handle is the window handle for the window.

First, I take a note of whether the app's activation status -- it's passed as a boolean in wParam. A typecast is required to convert it into a boolean value, since it's passed as something of type wParam. Now we know whether the app is doing stuff.

If we're active then it means we've been switched back from an inactive state -- in this case, we have to restore everything!

It's often the case that we'll lose exclusive mode when running fullscreen once the user alt-tabs. Therefore, the next step is to set the cooperative level back to the wanted value (exclusive, fullscreen). This takes some time, unfortunately, so we have to sit around and wait to see whether it works. I added a sleep(0) in there while we're waiting. We can use the TestCooperativeLevel method of IDirectDraw7, which returns whether the exclusive mode is set yet. There may be a better method to waste time than Sleep(0); investigate this.

Once we've done that, we have to restore the surfaces. This is done in my function "ReloadAllImages." First, we can use IDirectDraw7.RestoreAllSurfaces, which does the hard part for us. The only task left here is reload images for surfaces that are in video memory (system memory ones won't be wiped out).

The above is how I do it and it seems to work fine. Any corrections are much appreciated. Of course, it's based on my non-component-based stuff rather than a specific set. Making this relevant to your app is left as an exercise (to be done in public so we all learn from it, of course ).

Now, I haven't used D3D yet, so I can't answer that case. I'll let one of the other dudes answer it -- I think there's an equivalent TestCooperativeLevel method somewhere and I remember something about D3DPOOL_MANAGED (or something similar) textures being reloaded by the system. I also remember something about a reset method that must be called for something. This is all vague, but hopefully it's not wrong and will give someone an idea of where to begin.

Remember that you'll have to re-acquire DirectInput things. This should not be a problem if you check for the appropriate "not acquired" return values for the important functions.