JumpingJacks
JumpingJacks

Reputation: 277

How to get the screen resolution without Windows Forms reference?

I need to get the resolution of the desktop my test runs on. Previously I was grabbing the resolution like this:

Screen screen = Screen.PrimaryScreen;
int screenWidth = screen.Bounds.Width;
int screenHeight = screen.Bounds.Height;

Unfortunately, using System.Windows.Forms isn't possible anymore. My project is .NET Core, so preferably I need a NuGet package for this.

If anyone's got any suggestions I'd appreciate it.

Upvotes: 10

Views: 5997

Answers (1)

dymanoid
dymanoid

Reputation: 15197

If you don't want to use System.Windows.Forms (or cannot), you can get the screen resolution by using a Windows API function EnumDisplaySettings.

To call the WinAPI function, you can use the P/Invoke feature that is also available on .NET Core. Please note that this will only work on a Windows system, because there's no WinAPI on non-Windows targets.

The function declaration looks as follows:

[DllImport("user32.dll")]
static extern bool EnumDisplaySettings(string deviceName, int modeNum, ref DEVMODE devMode);

You also need the WinAPI DEVMODE struct definition:

[StructLayout(LayoutKind.Sequential)]
struct DEVMODE
{
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
  public string dmDeviceName;
  public short dmSpecVersion;
  public short dmDriverVersion;
  public short dmSize;
  public short dmDriverExtra;
  public int dmFields;
  public int dmPositionX;
  public int dmPositionY;
  public int dmDisplayOrientation;
  public int dmDisplayFixedOutput;
  public short dmColor;
  public short dmDuplex;
  public short dmYResolution;
  public short dmTTOption;
  public short dmCollate;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
  public string dmFormName;
  public short dmLogPixels;
  public int dmBitsPerPel;
  public int dmPelsWidth;
  public int dmPelsHeight;
  public int dmDisplayFlags;
  public int dmDisplayFrequency;
  public int dmICMMethod;
  public int dmICMIntent;
  public int dmMediaType;
  public int dmDitherType;
  public int dmReserved1;
  public int dmReserved2;
  public int dmPanningWidth;
  public int dmPanningHeight;
}

Actually, you don't need most of this structure's fields. The interesting ones are dmPelsWidth and dmPelsHeight.

Call the function like this:

const int ENUM_CURRENT_SETTINGS = -1;

DEVMODE devMode = default;
devMode.dmSize = (short)Marshal.SizeOf(devMode);
EnumDisplaySettings(null, ENUM_CURRENT_SETTINGS, ref devMode);

Now you can check the screen resolution in the dmPelsWidth and dmPelsHeight fields of the devMode struct.

Since we specify null as first argument, the function describes the current display device on the computer on which the calling thread is running.

Upvotes: 13

Related Questions