Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

In my windowed mode XNA game when the user resizes the window the game stops updating the window and the last frame drawn is stretched and distorted until the user releases the mouse and the resize completes.

Is there any way to have the game continue to run "normally", updating frames and redrawing the screen, during the resize event?

I realize that keeping the render loop going while resizing may not be possible or recommended due do hardware managed resources getting continually created and destroyed, but is there any way to stop the ugly stretching? Ideally by leaving the existing frame unscaled in the top left, or with a black screen if that isn't possible.

share|improve this question
    
Register an event for the window resize and update the GraphicsDevice resolution. This may update the aspect ratio and fix the stretching. –  Gustavo Maciel Oct 26 '12 at 21:17
    
I don't know about C#/XNA, but in C++/D3D I just had the render loop running in a separate thread from the main thread with the message loop. The main thread performs the buffer resize when a resize event occurs, synchronized through a mutex. –  melak47 Oct 26 '12 at 21:21
1  
Gustavo, I already handle that event for other purposes in the game. Unfortunately it doesn't fire until after the user releases the mouse when the re-size is complete. –  Bradley Uffner Oct 26 '12 at 21:31
    
This question/answer pair might be helpful. It tells you how to continue rendering (although it doesn't fix stretching). –  Andrew Russell Mar 20 '13 at 3:09
add comment

1 Answer

There are at least 3 messages that you can track.

  • WM_SIZE - window resizing, mini/maximization, fullscreen/windowed switching. You shall read into wParam to find out what exactly happened and to lParam for current size.
  • WM_ENTERSIZEMOVE - begin window resizing in windowed mode
  • WM_EXITSIZEMOVE - end window resizing in windowed mode

Usually you will not want resize your app every frame between WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE because its too way slooow and ugly. But give it a try, its surely nicely than stretching, maybe you'll like it =)

case WM_SIZE:
    // Save the new client area dimensions.
    m_ptViewportSize.x  = LOWORD(lParam);
    m_ptViewportSize.y = HIWORD(lParam);
    if( wParam == SIZE_MINIMIZED )
    {
        m_bAppSuspended = true;
        m_bMinimized = true;
        m_bMaximized = false;
    }
    else if( wParam == SIZE_MAXIMIZED )
    {
        m_bAppSuspended = false;
        m_bMinimized = false;
        m_bMaximized = true;
        OnResize();
    }
    else if( wParam == SIZE_RESTORED )
    {
        // Restoring from minimized state
        if( m_bMinimized )
        {
            m_bAppSuspended = false;
            m_bMinimized = false;
            OnResize();
        }
        // Restoring from maximized state
        else if( m_bMaximized )
        {
            m_bAppSuspended = false;
            m_bMaximized = false;
            OnResize();
        }
        else if( m_bResizing )
        {
            // Resizing in processs
            // You woldn't wanto to handle a massive stream of
            // WM_SIZE here because buffers resizing is very slow
        }
        else
        {
            // Resizing finished and you can handle it. For ex. with 
            // m_SwapChain->SetFullscreenState
            OnResize();
        }

    }
    return 0;

// WM_EXITSIZEMOVE is sent when the user grabs the resize bars.
case WM_ENTERSIZEMOVE:
    m_bAppSuspended = true;
    m_bResizing  = true;
    g_pTimer->Stop();
    return 0;
// WM_EXITSIZEMOVE is sent when the user releases the resize bars.
// Here we reset everything based on the new window dimensions.
case WM_EXITSIZEMOVE:
    m_bAppSuspended = false;
    m_bResizing  = false;
    g_pTimer->Start();
    OnResize();
    return 0;
share|improve this answer
1  
Handling windows messages in .NET involves overriding System.Windows.Forms.Form.WndProc(). When working in XNA, you don't have direct access to a Form to override that method. While it is possible to do, it's not a trivial amount of work and would have to circumvent XNA's design. –  Cypher Oct 26 '12 at 22:28
    
Should someone choose to take this path, this list of wm_* constants should prove to be useful: pinvoke.net/default.aspx/Constants/WM.html –  Cypher Oct 26 '12 at 22:29
    
Like others have said, I would still need a way to short circuit the XNA "engine" and cause it to draw again during the correct events. From what I can tell XNA sort of "goes to sleep" during the resize procedure. –  Bradley Uffner Oct 28 '12 at 23:30
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.