Thread: DirectX Mode Switching (Fullscreen<->Windowed)

  1. #1
    Magically delicious LuckY's Avatar
    Join Date
    Oct 2001
    Posts
    856

    DirectX Mode Switching (Fullscreen<->Windowed)

    So, how is this supposed to be done? I am having a heck of a time trying to find code samples with google.

    What I'm trying is just (fullscreen->windowed, for example): release back surface, release front surface, release ddraw object, adjust window size/style, init new ddraw object, set coop level, set display mode, create surfaces/clipper, recreate bitmap surfaces. I stop any rendering while all that happens. When I try to do it, it suicides on me.

    Do you have any links or code samples demonstrating how to switch modes between fullscreen ("exclusive") and windowed in DirectX 7.0 (2D btw).

  2. #2
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    You don't need to do all of that. There is no need to release the buffer or release any DirectX interface. All you need to ensure is that updates to your game are NOT written out to the buffer. Essentially you update the game but you don't draw anything. This will ensure you are not trying to write to a surface that has lost the focus. So when you lose focus - stop rendering the game and go into a 'memory only' update mode. As soon as the user switches back, negate the flag and all new rendering will then match what has been updated in memory. Essentially you are always updating the game in memory. So when you draw...you are simply drawing based on information in memory.

    Check the DirectX SDK, but I'm almost 95% sure that you do not need to create a new DirectX object. This will certainly crash and hose the system until you reboot.

  3. #3
    Magically delicious LuckY's Avatar
    Join Date
    Oct 2001
    Posts
    856
    Okay, so what you're saying is that I need to do everything I listed except for the releasing/recreating of the DirectDraw7 object?

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Well sorta. Stop drawing is all you need to do. Don't even enter the render function if you do not have the focus. Checking once per frame shouldn't hurt too bad. I would check once at the start of the render to see if you do have the focus. If so, draw away. Checking on each write to the buffer would be a bad design. Check once and then access the buffer or skip the function entirely.

    However with a clever use of function pointers you could boil this down to a simple pointer swap. If the window has the focus set the pointer to the render function. If not, set the pointer to another function - perhaps to help with background processing or something.

  5. #5
    Magically delicious LuckY's Avatar
    Join Date
    Oct 2001
    Posts
    856
    Whoa... Are we talking about the same thing here? I am looking for a way to dynamically switch between fullscreen (exclusive) and windowed mode. How is not rendering a frame going to switch me from one mode to the other? Btw, to be clear, I am already disallowing any rendering while I am doing the switch, but continuing to update. It's just the switching part that I'm having trouble with...

    *scratches head in confusion*

    It's not that I don't appreciate the help. I just don't understand it. Thanks Bubba.

  6. #6
    Registered User
    Join Date
    Apr 2002
    Posts
    1,571
    What do you mean it suicides on you? Is it a hard crash? You should turn up the DirectX Debug Output level to max and run it through the debugger. It sounds like you are doing it correctly to me.

    more:
    Anytime you use a surface method like Blt or Flip that operates on the surface you need to check the return value for DDERR_SURFACELOST. If it's lost you will need to re-load it.
    Last edited by MrWizard; 09-20-2004 at 12:39 PM.
    "...the results are undefined, and we all know what "undefined" means: it means it works during development, it works during testing, and it blows up in your most important customers' faces." --Scott Meyers

  7. #7
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    We are talking about the same thing. If the window has been minimized then you should not render anything. If the window is, well in a window and not fullscreen, then you need to do exactly what Mr. Wizard says. The SDK goes over this process in very great detail.

  8. #8
    Magically delicious LuckY's Avatar
    Join Date
    Oct 2001
    Posts
    856
    Okay I still need some help with this. For the life of me I cannot determine how to switch back and forth between windowed and fullscreen (exclusive) mode. When the user hits the key, this function is called:
    Code:
    BOOL DXAppWin::ChangeDisplayMode(BOOL bFullScreen, int nWidth, int nHeight, int nBPP) {
      // only do this when we're active
      if (!IsActive())
        return FALSE;
    
      // do not render any frames until we're done
      m_bActiveApp = FALSE;
    
      // print a debug message
      if (bFullScreen)
        PrintDebugMsg(TRUE, TRUE, _T("Changing game display to fullscreen mode (%dx%dx%d)"), 
          m_nWidth, m_nHeight, m_nBitsPerPixel);
      else
        PrintDebugMsg(TRUE, TRUE, _T("Changing game display to windowed mode (%dx%d)"), 
          m_nWidth, m_nHeight);
    
      // release all DirectDraw surfaces (m_lpFront and m_lpBack)
      DDReleaseSurfaces();
    
      // set the new display data
      if (nWidth > 0)
        m_nWidth  = nWidth;
    
      if (nHeight > 0)
        m_nHeight = nHeight;
    
      if (nBPP > 0) {
        switch (nBPP) {
          case 8:
          case 16:
          case 24:    
            m_nBitsPerPixel = nBPP;
          break;
    
          case 32:
          default: 
            m_nBitsPerPixel = 32;
          break;
        }
      }
    
      m_bFullScreen = bFullScreen;
    
      // finalize the mode change by reinitializing the surfaces
      while (true) {
        if (!DDSetCoopLevel())      break;
        if (!DDSetDisplayMode())    break;
        if (!DDCreateSurfaces())    break;
        if (!InitBitmap())          break;// just set old pointers to the new surfaces
    
        // determine the new window style
        int nWndStyle = m_bFullScreen ? WS_POPUPWINDOW : 
          WS_OVERLAPPEDWINDOW & ~(WS_MAXIMIZEBOX | WS_THICKFRAME);
    
        // change the window style
        ::SetWindowLong(m_hWnd, GWL_STYLE, nWndStyle);
    
        if (!m_bFullScreen) {
          // move window to the top left corner
          SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
        }
    
        m_bActiveApp = TRUE;
    
        return TRUE;
      }
    
      // something failed so reactivate the app, then close it
      m_bActiveApp = TRUE;
      Close();
    
      return FALSE;
    }
    If you can provide me with any assistance, please do (sample code is very welcome). Thanks.

    [edit]
    By the way, when I run this the way it is I am almost successful going from windowed to fullscreen. The only problem is that nothing gets drawn to the screen except GDI drawing and filling the back surface with a color.
    Going from fullscreen to windowed is a much different story. The entire game screen disappears and I see some of my desktop (and other running apps) but with pieces of it blacked out and the game continues running (I know because I hear the music and the game responds to my mouse and keyboard input correctly) but there is no window anywhere to be seen.
    [/edit]

    [edit]
    Okay, I've _finally_ figured it out. It was simply that my bitmaps were screwed once I did the mode switch and I wasn't properly handling them. So now before the mode switch I release all the bitmap surfaces and after the mode switch I recreate them. I don't actually know if that's quite proper, but it seems to work.
    [/edit]
    Last edited by LuckY; 12-09-2004 at 09:40 AM.

  9. #9
    Magically delicious LuckY's Avatar
    Join Date
    Oct 2001
    Posts
    856
    For anyone else who ever might come looking for a solution to the same problem, here is the main body my final mode change function:
    Code:
      DWORD dwWndStyle = GetWindowStyle(m_hWnd);
      if (m_bFullScreen) {
        // determine the new window style
        dwWndStyle = WS_POPUP | WS_VISIBLE;
    
        // change the window style
        ::SetWindowLong(m_hWnd, GWL_STYLE, dwWndStyle);
      }
      else {
        // restore the display mode
        m_lpDD->RestoreDisplayMode();
    
        // determine the new window style
        dwWndStyle &= ~WS_POPUP;
        dwWndStyle |= WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
    
        // change the window style
        ::SetWindowLong(m_hWnd, GWL_STYLE, dwWndStyle);
        
        // disable the close ('[x]') button in the system menu of windowed apps
        EnableMenuItem(GetSystemMenu(m_hWnd, FALSE), SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
    
        // Resize the window so that the client area is m_nWidth x m_nHeight
        RECT rect = { 0, 0, m_nWidth, m_nHeight };
        AdjustWindowRectEx(&rect, GetWindowStyle(m_hWnd), GetMenu(m_hWnd) != NULL,
          GetWindowExStyle(m_hWnd));
    
        // adjust the size of the window
        SetWindowPos(m_hWnd, NULL, 0, 0, rect.right - rect.left,
          rect.bottom - rect.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
      }
    
      // finalize the mode change by reinitializing the surfaces
      while (true) {
        if (!DDSetCoopLevel())      break;
        if (!DDSetDisplayMode())    break;
        if (!DDCreateSurfaces())    break;
        if (!InitBitmap())          break;
    
        m_bActiveApp = TRUE;
    
        return TRUE;
      }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. console mode and service mode
    By George2 in forum C# Programming
    Replies: 0
    Last Post: 06-01-2008, 01:42 AM
  2. DirectSound header issues
    By dxfoo in forum C++ Programming
    Replies: 0
    Last Post: 03-19-2006, 07:16 PM
  3. DirectX app won't compile on release mode
    By confuted in forum Game Programming
    Replies: 3
    Last Post: 08-02-2003, 11:23 AM
  4. Shortening main
    By pdstatha in forum C Programming
    Replies: 1
    Last Post: 04-03-2002, 04:56 PM
  5. free() usage
    By pdstatha in forum C Programming
    Replies: 5
    Last Post: 03-13-2002, 09:28 AM