Determine the properties of the monitor the game is currently on

Hey guys!

Need a bit of wisdom…

Given a situation where I have multiple monitors with different native ratios on the same machine (1,7777, 1.6 etc);

And my application uses GraphicsDeviceManager.HardwareModeSwitch set to false;

I want to be able to move the application in window mode to any monitor and when switching to full screen on that monitor, to be able to get the ratio of THAT monitor I’m on. Doesn’t matter if I get the width/height and calculate myself or I get the AspectRatio.

The way I figured I need to do that is to identify on which monitor I am first, and maybe update the state when moving the window.

However, I don’t seem to find a good way to make that determination. Played around with the GraphicsAdapter. I am certain there is a mechanism somewhere, because each time I go full screen after moving the window to a new monitor, the game knows to go full screen on that monitor. Even if I play around in between monitors, there’s that perfect pixel in the middle that decides whether to fullscreen on one monitor or another.

Edit. I thought to play with the Window and that led me to the ClientBounds. I noticed that the X is global, so that could be a way, but what if I align the monitors in a weird way? Not convinced that I’m on the best path, but will continue to investigate this one for now.

Any other advice?

Thanks in advance!

I discovered a satisfactory solution thought it’s in a different order of operations than I initially imagined.
I simply switch to full-screen and then the Window.ClientBounds will contain the rectangle of what the Window made fulscreen on. From there it’s easy.

You can get the current monitor’s resolution with these (current monitor is the one the window is in):

GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width
GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height

I wrote a bit about it here: https://learn-monogame.github.io/how-to/fullscreen/

Hello there, @Apostolique

Thanks for your reply! Actually, I was reading your article yesterday when I initially wrote this.

Experimentally, I was able to determine that GraphicsAdapter.DefaultAdapter is in fact the default monitor, not the one the window is currently at. It is the one that the application starts on and returns the same value regardless of where you move the window.

I am testing this with Monogame 3.8 on windows 10 and two monitors, one at full HD and a test monitor at 1680x1050.

Might be a bug, I tested the other day and it did return new values when I was moving the window around. Unless I misunderstand what you mean.

Not sure what it is, you clearly understood correctly, last phrase you wrote is exactly it.
I don’t know what to say, I can also test on a mac, to see what happens there with a second monitor. At least I’ll try and document my experiments and list them here as I go.

Thanks man!

1 Like

Just gave this a try and there are a number of inconsistences between platforms. These are the results I got.

XNA

GraphicsAdapter.DefaultAdapter.CurrentDisplayMode - Always startup display, doesn’t change
GraphicsAdapter.Adapters - Contains a list of all displays
GraphicsDevice.Adapter.CurrentDisplayMode - Current display for window location

WindowsDX

GraphicsAdapter.DefaultAdapter.CurrentDisplayMode - Correct (matches XNA)
GraphicsAdapter.Adapters - Correct (matches XNA)
GraphicsDevice.Adapter.CurrentDisplayMode - Correct (matches XNA)

DesktopGL

GraphicsAdapter.DefaultAdapter.CurrentDisplayMode - Wrong (changes when window moved)
GraphicsAdapter.Adapters - Wrong (only contains display with window location)
GraphicsDevice.Adapter.CurrentDisplayMode - Correct (matches XNA)

DesktopGL seems to have two issues that need resolving to match XNA’s behaviour. If XNA is the intended behaviour then you should be using GraphicsDevice.Adapter.CurrentDisplayMode instead of GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.

2 Likes

@Squarebananas thanks a lot for this, I was about to do something similar.

Well, I’m developing for Win and Mac, so I think I’ll stick to doing the math after I go full screen and not rely on CurrentDisplayMode. Does that sound resonable, or do you think I should explore some other path?

I don’t have any suggestions for Mac, but for Windows you can create a library that references the System.Windows.Forms assembly and utilize the functionality in there. Alternatively (or complimentary) there’s a plethora of Win32 API calls you can make (pinvoke.net is your friend). When I have to do screen tom-foolery, that’s usually my go to.

You can abstract this away behind an interface and implement it differently for each platform. I just don’t know any of these tricks on the Mac platform.

1 Like

I’ve only used Window.ClientBounds before and haven’t seen an issue yet. Using Adapter.CurrentDisplayMode may also work, just not DefaultAdapter.CurrentDisplayMode as that shouldn’t update when changing window.

These are probably the lines to understand what Monogame is doing (looking up the Forms/SharpDX/SDL api documentation for these functions may also help):

WindowsDX Window.ClientBounds uses:
System.Windows.Forms.Form.PointToScreen
System.Windows.Forms.Form.ClientSize

WindowsDX GraphicsDevice.Adapter uses
SharpDX.DXGI.Output.Description.DesktopBounds

DesktopGL Window.ClientBounds uses:
Sdl.Window.GetPosition

DesktopGL GraphicsDevice.Adapter uses:
Sdl.Display.GetWindowDisplayIndex
Sdl.Display.GetCurrentDisplayMode