What actions, should I perform in a DirectX 11 application to correctly process Alt+Tab events from Windows?

My application is in fullscreen mode.

I expect my application to minimize to taskbar nicely, but it freezes for 20 seconds instead and no window minimization happens.

I know I can minimize the window by calling to ShowWindow, but what's up with the freeze?


2 Answers 2


ALT+TAB is generally handled through WM_ACTIVATEAPP and "FSE" games switch out/in of fullscreen mode based on this message.

With DXGI you can manually implement ALT+ENTER using DXGI_MWA_NO_ALT_ENTER on the MakeWindowAssociation method. You then in your WndProc you detect it yourself processing the WM_SYSKEYDOWN message:

    if (wParam == VK_RETURN && (lParam & 0x60000000) == 0x20000000)
        // Implements the classic ALT+ENTER fullscreen toggle

That said, many games use 'fake fullscreen' instead of 'exclusive full screen' for better behavior when interacting with multiple monitors, ALT+TAB switching, etc. Exclusive fullscreen can get pretty quirky/tricky to do.

You can also just use 'fullscreen is really maximize without a window border' which is what I do for the directx-vs-templates to keep them simple. In other words, I never try to change the display resolution.

See DirectX Graphics Infrastructure (DXGI): Best Practices

  • \$\begingroup\$ But what does Alt Enter has to do with Alt Tab? \$\endgroup\$
    – PaulD
    Commented Apr 4, 2019 at 15:27
  • \$\begingroup\$ Ah, sorry... You don't mean "Fullscreen vs. windowed" (ALT+ENTER) you mean "Switch away" (ALT+TAB). In that case, you need to just properly handle losing focus for your window. The best practices is still probably the best doc out there for doing fullscreen with DXGI. \$\endgroup\$ Commented Apr 4, 2019 at 18:44

Here is what I've found works. All of this information is probably scattered around the DXGI documentation on various disconnected pages; it's been a while since I've reviewed it.

For windowed modes (including borderless) Alt-Tab just works and you don't need to do anything special.

For fullscreen exclusive modes, first of all, always create your window (using CreateWindow(Ex)) with the normal title bar and borders as if it were for a windowed mode. Never touch them afterwards; SetFullscreenState will remove the window decorations for exclusive fullscreen modes automatically for you, so just let it do it's work and everything else will go easier on you.

An aside on MakeWindowAssociation

If you're using MakeWindowAssociation, you may have found that it doesn't honour the flags you give it, and DXGI tries to handle Alt-Enter (yes, I know you asked about Alt-Tab, bear with me) anyway. The correct way to use MakeWindowAssociation is to call it from the parent DXGIFactory for your swapchain, like so:

if (SUCCEEDED (SwapChain->GetParent (&IID_IDXGIFactory, (void **) &pFactory)))
    pFactory->MakeWindowAssociation (hWnd, DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER);
    pFactory->Release ();

My recollection is that none of this was clearly called-out in the documentation.

Deal with Alt-Tab by responding to WM_ACTIVATE messages.

For Alt-Tabbing away, the first thing I do is call IDXGISwapChain::SetFullscreenState with FALSE. This will give you better behaviour, and you won't end up with any "frozen" topmost exclusive fullscreen modes.

The next thing I do is use ShowWindow with SW_MINIMIZE - this nicely tucks the window away, minimized to the taskbar.

The final consideration is that this will generate a WM_SIZE message with size {0,0} so when you're responding to WM_SIZE for mode changing you need to be aware of this, and do whatever is needed for your program to stop it exploding in your face.

For Alt-Tabbing back, I do the following:

  • SetForegroundWindow
  • ShowWindow with SW_RESTORE
  • Pump my message loop to let everything bring itself up to date
  • IDXGISwapChain::SetFullscreenState with TRUE.

All together, this gives a clean, smooth experience with no freezes, hangs, stuck foreground windows that you can't get rid of, or any other nastiness like that.

  • \$\begingroup\$ Thanks, the first part of this worked really well. For those of not familiar with Windows programming, what do you mean by "pump my message loop"? \$\endgroup\$ Commented Jan 8, 2023 at 22:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .