Change window size mid-game

In the options of my game, I want to allow the user to switch between full screen and windowed. When it goes to windowed, for simplicity, I want to force it to use a 1280x720.

Below is the code I call when they change the windows/fullscreen option…

    public void SetScreen()
    {
        if (this.currentMenu.CurrentResolutionOption == Menu.ResolutionOption.FullScreen)
        {
            this.graphics.IsFullScreen = true;
            this.graphics.PreferredBackBufferWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width;
            this.graphics.PreferredBackBufferHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height;
        }
        else
        {
            this.graphics.IsFullScreen = false;
            this.graphics.PreferredBackBufferWidth = 1280;
            this.graphics.PreferredBackBufferHeight = 720;
        }

        this.graphics.ApplyChanges();
    }

This correctly changes from full screen to windowed, but the size of the window stays at the size of the full screen instead of switching to 1280x720.

Any idea how I can get the window size to change too? Changing the window size only seems to work when I initially set the value in Initialize() or Game1() and not later.

This is how i handle different resolutions (you can also use ScaleMatrix in your spritebatch.Begin() to scale your sprites too if thats useful to you, also GameWidth and GameHeight is the real game’s width and height, not the window’s size

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;

namespace GameName1{
static class Resolution
{
    static public Matrix ScaleMatrix { get; set; }
    static public Vector2 Scale { get; set; }
    static public int GameWidth { get; set; }
    static public int GameHeight { get; set; }
 #if WINDOWS
    static public int ScreenWidth { get; set; }
    static public int ScreenHeight { get; set; }
    static public Boolean WasResized { get; set; }
    static private int PreviousWindowWidth;
    static private int PreviousWindowHeight;
 #endif


    static public void Initialize(GraphicsDeviceManager graphics)
    {
#if WINDOWS
        ScreenWidth = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width;
        ScreenHeight = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height;
        PreviousWindowWidth = graphics.PreferredBackBufferWidth;
        PreviousWindowHeight = graphics.PreferredBackBufferHeight;
        WasResized = false;
 #endif
        GameWidth = 720;
        GameHeight = 1080;
        CalculateMatrix(graphics);
    }
    

#if WINDOWS
    static public void Update(Game game, GraphicsDeviceManager graphics)
    {
        if (WasResized)
        {
            if (graphics.PreferredBackBufferWidth < Resolution.GameWidth / 4)
            {
                if (graphics.PreferredBackBufferWidth == 0) graphics.PreferredBackBufferWidth = PreviousWindowWidth;
                else graphics.PreferredBackBufferWidth = Resolution.GameWidth / 4;
            }
            if (graphics.PreferredBackBufferHeight < Resolution.GameHeight / 4)
            {
                if (graphics.PreferredBackBufferHeight == 0) graphics.PreferredBackBufferHeight = PreviousWindowHeight;
                else graphics.PreferredBackBufferHeight = Resolution.GameHeight / 4;
            }
            graphics.ApplyChanges();
            CalculateMatrix(graphics);
            PreviousWindowWidth = graphics.PreferredBackBufferWidth;
            PreviousWindowHeight = graphics.PreferredBackBufferHeight;
            WasResized = false;
        }
    }
#endif


    static void CalculateMatrix(GraphicsDeviceManager graphics)
    {
        ScaleMatrix = Matrix.CreateScale((float)graphics.PreferredBackBufferWidth / GameWidth, (float)graphics.PreferredBackBufferHeight / GameHeight, 1f);
        Scale = new Vector2(ScaleMatrix.M11, ScaleMatrix.M22);
    }
}

}

Then in your Game1.cs

//at the constructor
this.Window.ClientSizeChanged += delegate { Resolution.WasResized = true; };

//in the initialize
Resolution.Initialize(graphics);

//in the update
Resolution.Update(this, graphics);

Maybe you need to call apply changes after setting fullscreen to false ? A temporary solution for the full screen specifically would be to make it borderless instead of using the full screen property here you press F11 to switch back and forth to full and windowed mode::

        //Get new states
        KeyboardState currentKeyboardState = Keyboard.GetState();

       //F11
        if (PreviousKeyboardState.IsKeyDown(Keys.F11) && !currentKeyboardState.IsKeyDown(Keys.F11))
        {
            if (game.Window.IsBorderless == true)
            {
                game.Window.Position = new Point((Resolution.ScreenWidth - Resolution.GameWidth) / 2, ((Resolution.ScreenHeight - Resolution.GameHeight) / 2) - 40);
                game.Window.IsBorderless = false;
                graphics.PreferredBackBufferWidth = Resolution.GameWidth;
                graphics.PreferredBackBufferHeight = Resolution.GameHeight;
                graphics.ApplyChanges();
            }
            else
            {
                game.Window.Position = new Point(0, 0);
                game.Window.IsBorderless = true;
                graphics.PreferredBackBufferWidth = Resolution.ScreenWidth;
                graphics.PreferredBackBufferHeight = Resolution.ScreenHeight;
                graphics.ApplyChanges();
            }
        }
        PreviousMouseState = currentMouseState;
        PreviousKeyboardState = currentKeyboardState;

I guess I’m not seeing what you’re doing differently than when I am. The just of changing your resolution code seems to be these three lines below, which is what I’m doing too. I already have the scaling stuff worked out (excluded for brevity) and full screen works right. It’s just going from full screen to windowed that leaves the size of the window at the same size as full screen.

graphics.PreferredBackBufferWidth = Resolution.GameWidth;
graphics.PreferredBackBufferHeight = Resolution.GameHeight;
graphics.ApplyChanges();

I have never made IsFullscreen property or ToggleFullScreen() to work mid-game, this is why i suggested:

A temporary solution for the full screen specifically would be to make it borderless instead

Personally i find borderless full screen more attractive than the old styled fullscreeen, this is why i never looked into it more when i had the same problem with you. But hopefully, someone can give us a better answer on how to use the IsFullscreen property.

You uses WinDX ? Maybe this is little bug - try write graphics.HardwareModeSwitch = false; in Game constructor.

I think you misunderstand. Full screen works fine, its windowed mode that has problems. Say your desktop resolution is 1800x1400. The game will run at 1800x1400 full screen. When you switch to windowed, it should switch to the window to the size of the actual game (1280x720). No matter what I do though, I can’t get the window to be any smaller than 1800x1400. It seems only during Game1() or Initialize() can you specific the size of the window.

HardwareModeSwitch isn’t a property on graphics. I can’t find any mention of that on other objects either :shrug:

I understood well what you said

It seems only during Game1() or Initialize() can you specific the size of the window.

So both windowed and fullscreen mode don’t work mid-game (since i consider having a giant windowed game that can’t be re-sized, does not qualify as “works”) and your “Full screen works fine” because it is in the Game1 constructor or Initialize() , which is what i also experienced a couple of months ago, this is why i suggested using borderless fullscreen. Which is just a suggestion and an alternative, not a direct solution to your problem, i know.

This is old, but I found this thread from a google search, and suspect I had the same problem as the OP, and I figured out a solution a few hours later, so, might as well update the thread with a possible solution, for the next person who finds the thread.

My code looked pretty much identical to the OP, and when switching from fullscreen TO windowed, the window would not be the desired 1280x720. It would be some other size. But, my game code thought it was 1280x720, so everything looked a little bit shrunk, the wrong dimensions in-game.

To fix it, I went from this:

this.graphics.IsFullScreen = false; this.graphics.PreferredBackBufferWidth = 1280; this.graphics.PreferredBackBufferHeight = 720; this.graphics.ApplyChanges();

to this:

this.graphics.IsFullScreen = false; this.graphics.PreferredBackBufferWidth = 1280; this.graphics.PreferredBackBufferHeight = 720; this.graphics.ApplyChanges(); this.graphics.PreferredBackBufferWidth = 1280; this.graphics.PreferredBackBufferHeight = 720; this.graphics.ApplyChanges();

Yup, literally just do it twice.

2 Likes