C# - 如何在多显示器上下文中获得真实的屏幕分辨率?

Dav*_*NNE 5 c# wpf winapi interop multiple-monitors

对于我的一个应用程序(用 WPF 编写),我需要获取有关监视器的一些信息:当前分辨率、比例因子和实际分辨率。

我知道这个问题已经被问过很多次了,但我无法在所有讨论这个问题的 SO 问题中找到一个好的答案......

例如,就我而言,我按以下顺序放置了 3 个显示器:

  • 显示器 1(集成笔记本电脑屏幕):1920x1080,缩放比例为 125%
  • 显示器 2 (LG 22"):1920x1080,100% 缩放(主显示器)
  • 显示器 3 (LG 22"):1920x1080,100% 缩放

使用 System.Windows.Forms.Screen.AllScreens 时,我的第一台显示器的分辨率为 1536x864。没关系,因为 1536*1.25 = 1920。但我找不到 1.25 或 1920 ^^(对于其他显示器,这没关系,因为它们按 100% 缩放)。

但是如果我将监视器 1 设置为主监视器,我可以获得它的实际分辨率,但是对于监视器 2 和 3,我得到 2400*1350...它是 1920x1080 乘以主监视器的缩放因子:1.25

我尝试了很多方法已经2天了。我已经在 Windows.Forms 中尝试过 AllScreens。在 WinAPI 中,我尝试过 EnumDisplayMonitors、GetDeviceCaps、GetScaleFactorForMonitor、GetDpiForMonitor ......对于我的第一台显示器,一切总是给我一个 100% 的缩放因子或 96 的 DPI,这是一个错误......

您知道获取这些信息的安全方法吗?在 WMI 中,在注册表中,等等...

谢谢你的帮助 !

(PS:如果需要,我可以提供我尝试过的代码示例,但我不想淹没第一篇文章)

编辑:我忘了提到我需要在没有任何可视化应用程序的情况下获取这些信息(我的 DLL 是从 VB 应用程序调用的)

col*_*909 9

我有几乎完全相同的设置。我能够通过EnumDisplaySettings使用 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;
}
Run Code Online (Sandbox Code Playgroud)

和输出:

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

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

Device: \\.\DISPLAY3
Real Resolution: 1920x1080
Virtual Resolution: 1920x1080
Run Code Online (Sandbox Code Playgroud)

/sf/answers/2580531901/ http://pinvoke.net/default.aspx/user32/EnumDisplaySettings.html?diff=y