C# - How to get real screen resolution in multiple monitors context?
Asked Answered
A

1

9

For one of my application (write in WPF), I need to get some informations about monitors : Current resolution, scaling factor and real resolution.

I know this question has been asked many times but I'm not able to find a good answer in all SO questions that talked about that...

In my case for example, I have 3 monitors placed in this order :

  • Monitor 1 (integrated laptop screen) : 1920x1080, scaled at 125%
  • Monitor 2 (LG 22") : 1920x1080, scaled at 100% (PRIMARY MONITOR)
  • Monitor 3 (LG 22") : 1920x1080, scaled at 100%

When using System.Windows.Forms.Screen.AllScreens, I obtain a resolution of 1536x864 for my first monitor. It's OK because 1536*1.25 = 1920. But i'm not able to find either the 1.25 or the 1920 ^^ (for the other monitors it's OK because they're scaled at 100%).

But if I set monitor 1 to be primary I can obtain it's real resolution but for monitor 2 and 3 I obtain 2400*1350... It's 1920x1080 multiply by the primary monitor's scaling factor : 1.25

It's been 2 days since I try many ways. I've tried AllScreens in Windows.Forms. In WinAPI I've tried EnumDisplayMonitors, GetDeviceCaps, GetScaleFactorForMonitor, GetDpiForMonitor... Everything always give me a 100% scaling factor or a DPI of 96 for my first monitor which is an error...

Do you know a secure way to obtain these informations ? In WMI, in registry, etc...

Thanks for your help !

(PS : if needed I can provide code sample of what I tried but I don't want to flood this first post)

EDIT : I forgot to mention that I need to obtain these informations without any visual app (my DLL is called from a VB application)

Auditory answered 3/4, 2017 at 14:45 Comment(15)
How does your program declare its DPI awareness?Kopans
I haven't set anything in my program, just "add new project WPF" in Visual Studio :)Auditory
Well, it's time to find out, isn't it. You know what DPI awareness is right?Kopans
Not really... I've read some threads about that but it's not very clear in my head... Do you think that declaring DPI awareness in my program would help me finding these informations ?Auditory
I think you are not going to make any progress until you understand the concept of DPI awareness comprehensively.Kopans
WPF applications are system DPI aware by default. In .NET Framework 4.6.2 you can easily enable per monitor DPI awareness: github.com/Microsoft/WPF-Samples/tree/master/PerMonitorDPI.Satang
@david : OK I understand principe of scaling, I understand DPI in WPF context but I don't understand the relation between obtaining resolution and the fact that the app is DPI aware or not. Why these informations are not accessible via simple API ??Auditory
Yawn. Trying to work this out with an incomplete understanding is tedious. Don't waste your own time on this. Don't flail around in the dark. Back your own ability to be able to understand this.Kopans
@Satang : thanks for the link, I'll read carefuly but what I forgot to mention is my app should run in .Net 4.Auditory
Did you read this?: msdn.microsoft.com/en-us/library/windows/desktop/…Satang
@DavidHeffernan : it's not a question about wasting my time, I HAVE to do that, I'd prefer not but that's not the case. Could you try to help me or not ? Why a blank new WPF app always return 100% scaling ? Or a DPI of 96 ?Auditory
@Satang : thanks for the link, I will read that.Auditory
I can't help you until you understand DPI awareness. Sorry.Kopans
Oh yes, I wasn't asking you for learning me DPI awareness :) Thanks to mm8 links, I was able to find a demo app from Microsoft that can obtain good DPI for my screens. I now have to understand why my app wouldn't do that since they used GetDpiForMonitor as I was doing... (but maybe, as you said, understanding DPI awareness will help me for that point).Auditory
Main post edited : I forgot to mention that I need to obtain these informations without any visual app (my DLL is called from a VB application)Auditory
F
11

I have almost exactly the same setup. I was able to get the real resolution by calling EnumDisplaySettings using p/invoke.

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

const int ENUM_CURRENT_SETTINGS = -1;

foreach (Screen screen in Screen.AllScreens)
{
    var dm = new DEVMODE();
    dm.dmSize = (short)Marshal.SizeOf(typeof(DEVMODE));
    EnumDisplaySettings(screen.DeviceName, ENUM_CURRENT_SETTINGS, ref dm);

    Console.WriteLine($"Device: {screen.DeviceName}");
    Console.WriteLine($"Real Resolution: {dm.dmPelsWidth}x{dm.dmPelsHeight}");
    Console.WriteLine($"Virtual Resolution: {screen.Bounds.Width}x{screen.Bounds.Height}");
    Console.WriteLine();
}

[DllImport("user32.dll")]
static extern bool EnumDisplaySettings(string lpszDeviceName, int iModeNum, ref DEVMODE lpDevMode);

[StructLayout(LayoutKind.Sequential)]
public 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 ScreenOrientation 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;
}

And the output:

Device: \\.\DISPLAY1
Real Resolution: 1920x1080
Virtual Resolution: 1536x864

Device: \\.\DISPLAY2
Real Resolution: 1920x1080
Virtual Resolution: 1920x1080

Device: \\.\DISPLAY3
Real Resolution: 1920x1080
Virtual Resolution: 1920x1080

https://mcmap.net/q/271030/-detect-if-non-dpi-aware-application-has-been-scaled-virtualized http://pinvoke.net/default.aspx/user32/EnumDisplaySettings.html?diff=y

Fabri answered 29/1, 2019 at 15:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.