Fullscreen with multiple monitors / which monitor am I on?

So this question is a little tricky, and somewhat technical.

Basically, I have two monitors of different resolutions. I notice that whenever I make my game go fullscreen, it takes over whichever monitor the game window is on. That’s exactly how I’d want it, really.

However, there’s an issue: how do I know which resolution to set it to? The default GraphicsAdapter is of course not always going to be the one I want to use. I can cycle through the adapters, but how do I know which one I’m taking over?

1 Like

Is the adapter in GraphicsDevice not the one you’re looking for?

Windows or other?

Windows, usually it is the one set as the main display.

Go to Display Settings.

On a recent develop build and with a DX project, GraphicsDevice.Adapter will give the adapter of the output the game window is on. It changes if you move the window to another screen. But this is not properly implemented for DesktopGL.

1 Like

The problem is that the one in GraphicsDevice is the main display, but if you were to drag the game window to another screen and then fullscreen it, it will take over the secondary screen with the resolution of the main screen. This is not good.

The way I see it, there are two possible solutions: either make it move to the main display, or allow it to use the the resolution of the display it’s on.

Currently working on Windows, yes.

My issue is that users can just drag the window over to a secondary monitor, hit fullscreen, and it will take over the secondary monitor at the main display’s resolution, which may not have the same resolution.

Have you not implemented resolution selection yet? if not, get on it!

How is that solving his issue? Proper implementation of resolution selection will require to know bounds of active display, which is exactly what he is trying to get. Trust me, been there, done that. Users will find thousand ways to break it if it wont be perfectly userproof and this is one of information you need to make it so.

1 Like

Hmm…

I know there is a pattern for this…

@MrValentine that’ll be a good enough solution I suppose. I didn’t plan on implementing various resolutions for fullscreen since the game I’m currently working on should use very minimal resources, but it would be a possible solution to the problem.

@Ravendarke I’m able to get the resolutions for all of the monitors, I’m just not able to determine which monitor I’m on. If I create a menu where the user can select the resolution, that might be a good-enough solution.

1 Like

If you only want to get the bounds of the current monitor, that’s how I do it:

screen = Screen.FromControl(f);
zero = new Point(screen.Bounds.X, screen.Bounds.Y);

Not sure if this works on any other system than windows though…

2 Likes

This looks like the solution I need! I’ll try it out when I get back to work, thanks.

You’re welcome. If anything else arises, just ask. People here will always help best they can.

2 Likes

Hmmm. Just saw that you need to get the form first (the ‘f’), so here’s the whole code of the method.
I call it twice. Once with the saved (to the game-descriptor file) values and, should that go wrong (monitor setup changed, card changed, etc…) then it returns null and I start it a second time with a hardcoded fallback resolution (a low one)…

public static Rectangle? InitGraphicsMode(Game game, GraphicsDeviceManager graphicsDeviceManager, int width,
        int height,
        bool isFullScreen, float targetElapsedIntervalInMillis = 1000f / 60f,
        bool isSynchronizeWithVerticalRetrace = true, bool isFixedTimeStep = false,
        bool isPreferMultiSampling = true,
        SurfaceFormat preferredBackBufferFormat = SurfaceFormat.Color,
        DepthFormat preferredDepthFormat = DepthFormat.None, Point? zero = null)
{
    // Form.ActiveForm really gets the form of the currently active window. We want the game's window.
    var f = (Form) Control.FromHandle(game.Window.Handle);
    if (f == null)
        return null;

     // Quality switches.
    graphicsDeviceManager.PreferredBackBufferFormat = preferredBackBufferFormat;
    graphicsDeviceManager.PreferredDepthStencilFormat = preferredDepthFormat;
    // This tells MonoGame to not switch the mode of the graphics-card directly, but to scale the window.
    graphicsDeviceManager.HardwareModeSwitch = false;
    // This tells MonoGame to fetch pre DX9c devices as well.
    graphicsDeviceManager.GraphicsProfile = GraphicsProfile.Reach;
    // Enables anti-aliasing.
    graphicsDeviceManager.PreferMultiSampling = isPreferMultiSampling;
    // Set to true to set the draw-restriction to the refresh-rate of the monitor.
    graphicsDeviceManager.SynchronizeWithVerticalRetrace = isSynchronizeWithVerticalRetrace;
    // If set to false, you are unbinding update and draw thus allowing them to be called separately.
    game.IsFixedTimeStep = isFixedTimeStep;
    // Determines how often update will be called (works only if IsFixedTimeStep is true.
    // 60 times per second is the default value.
    game.TargetElapsedTime = TimeSpan.FromMilliseconds(targetElapsedIntervalInMillis);

    Screen screen;
    if (zero.HasValue && isFullScreen)
    {
        screen = Screen.FromPoint(new System.Drawing.Point(zero.Value.X, zero.Value.Y));
    }
    else
    {
        screen = Screen.FromControl(f);
        zero = new Point(screen.Bounds.X, screen.Bounds.Y);
    }

    var x = screen.Bounds.Width;
    var y = screen.Bounds.Height;

    width = Math.Min(width, x);
    height = Math.Min(height, y);

    if (!isFullScreen)
    {
        x = width + 16;
        y = height + 38;
        zero = zero + new Point((screen.Bounds.Width - width) / 2, (screen.Bounds.Height - height) / 2);
    }

    game.Window.IsBorderless = isFullScreen;

#if LINUX
			Debug.DLog("getting form...");
			Form form = Control.FromHandle(game.Window.Handle).FindForm();
			if (form != null)
			{
				Debug.DLog("setting location...");
				form.Location = new System.Drawing.Point(x, y);
			}
			else
			{
				Debug.DLog("form was null.");
			}
#else
    game.Window.Position = zero.Value;
#endif

    graphicsDeviceManager.PreferredBackBufferWidth = width;
    graphicsDeviceManager.PreferredBackBufferHeight = height;
    graphicsDeviceManager.IsFullScreen = isFullScreen;
    graphicsDeviceManager.ApplyChanges();
     f.SetDesktopBounds(zero.Value.X, zero.Value.Y, x, y);
    return new Rectangle(zero.Value.X, zero.Value.Y, width, height);
}

It’s mostly legacy, but it works. I don’t know if it still works on linux though… did once… long time ago. But now I don’t even know if the compiler switch LINUX still exists or not.

1 Like