C#-如何在多个监视器上下文中获得真实的屏幕分辨率? [英] C# - How to get real screen resolution in multiple monitors context?

查看:407
本文介绍了C#-如何在多个监视器上下文中获得真实的屏幕分辨率?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

我知道这个问题已经问过很多次了,但是我在所有有关此的SO问题中都找不到很好的答案...

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...

例如,在我的情况下,我按此顺序放置了3个监视器:

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

  • 显示器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%).

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%).

但是如果我将显示器1设置为主显示器,则可以得到它的真实分辨率,但是对于显示器2和3,我可以得到2400 * 1350 ...它是1920x1080乘以主要显示器的比例因子:1.25

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

距离我尝试了很多方法已经有2天了.我已经在Windows.Forms中尝试过AllScreens.在WinAPI中,我尝试了EnumDisplayMonitors,GetDeviceCaps,GetScaleFactorForMonitor,GetDpiForMonitor ... 一切总是为我的第一台显示器提供100%的比例因子或96的DPI,这是一个错误...

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...

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

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

感谢您的帮助!

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

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

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

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

推荐答案

我的设置几乎完全相同.我可以通过使用p/invoke调用EnumDisplaySettings来获得真正的分辨率.

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;
        }
    }
}

输出:

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

这篇关于C#-如何在多个监视器上下文中获得真实的屏幕分辨率?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆