问题
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)
回答1:
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;
namespace RealScreenResolution
{
class Program
{
const int ENUM_CURRENT_SETTINGS = -1;
static void Main(string[] args)
{
foreach (Screen screen in Screen.AllScreens)
{
DEVMODE 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")]
public static extern bool EnumDisplaySettings(string lpszDeviceName, int iModeNum, ref DEVMODE lpDevMode);
[StructLayout(LayoutKind.Sequential)]
public struct DEVMODE
{
private const int CCHDEVICENAME = 0x20;
private const int CCHFORMNAME = 0x20;
[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://stackoverflow.com/a/36864741/987968 http://pinvoke.net/default.aspx/user32/EnumDisplaySettings.html?diff=y
来源:https://stackoverflow.com/questions/43187663/c-sharp-how-to-get-real-screen-resolution-in-multiple-monitors-context