C# 使用C的有效友好监视器名称

C# 使用C的有效友好监视器名称,c#,winapi,display,monitor,names,C#,Winapi,Display,Monitor,Names,我的主要开发机器是一台笔记本电脑,有两个屏幕:一个内部屏幕和一个外部三星显示器 Generic PnP Monitor= 1366x768, Top: 0, Left: 1920 -> secondary display SF350_S24F350FH / S24F352FH / S24F354FH (HDMI)= 1920x1080, Top: 0, Left: 0 -> main display 我的代码是: Dispay.cs using System; us

我的主要开发机器是一台笔记本电脑,有两个屏幕:一个内部屏幕和一个外部三星显示器

    Generic PnP Monitor= 1366x768, Top: 0, Left: 1920 -> secondary display
    SF350_S24F350FH / S24F352FH / S24F354FH (HDMI)= 1920x1080, Top: 0, Left: 0 -> main display
我的代码是: Dispay.cs

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

internal class Display
{
  private Rectangle _bounds;
  private DisplayOrientation _orientation;
  private Rectangle _workingArea;
  private string _name,_deviceId;
  private static Display[] _displays;

  public Rectangle Bounds
  {
     get
     {
       return _bounds;
     }
  }

  public DisplayOrientation Orientation
  {
    get
    {
        return _orientation;
    }
  }

  public Rectangle WorkingArea
  {
    get
    {
        return _workingArea;
    }
  }

  public string DeviceId
  {
    get
    {
        return _deviceId;
    }
  }

  public string Name
  {
    get
    {
        return _name;
    }
  }

  public static DisplayImpl[] Displays
  {
    get
    {

        if (_displays == null) QueryDisplayDevices();

        return _displays;
    }

    private static void QueryDisplayDevices()
    {
            List<Display> list = new List<Display>();
            WinApi.MonitorEnumDelegate MonitorEnumProc = new WinApi.MonitorEnumDelegate((IntPtr hMonitor, IntPtr hdcMonitor, ref WinApi.RECT lprcMonitor, IntPtr dwData) => {
                WinApi.MONITORINFOEX mi = new WinApi.MONITORINFOEX() { Size = Marshal.SizeOf(typeof(WinApi.MONITORINFOEX)) };

                if (WinApi.GetMonitorInfo(hMonitor, ref mi))
                {
                    WinApi.DISPLAY_DEVICE device = new WinApi.DISPLAY_DEVICE();
                    device.Initialize();

                    if (WinApi.EnumDisplayDevices(mi.DeviceName.ToLPTStr(), 0, ref device, 0))
                    {
                        Display display = new Display()
                        {
                            _name = device.DeviceString,
                            _deviceId = mi.DeviceName,
                            _bounds=new Rectangle(mi.Monitor.Left,mi.Monitor.Top,mi.Monitor.Right-mi.Monitor.Left,mi.Monitor.Bottom-mi.Monitor.Top),
                            _workingArea = new Rectangle(mi.WorkArea.Left, mi.WorkArea.Top, mi.WorkArea.Right - mi.WorkArea.Left, mi.WorkArea.Bottom - mi.WorkArea.Top),
                        };
                        list.Add(display);
                    }
                }

                return true;
            });

            WinApi.EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, MonitorEnumProc, IntPtr.Zero);
            _displays=list.ToArray();

    }
  }

}
我得到了这些结果:

       Display 0:
          Name: Generic PnP Monitor
          DeviceId: \\\\.\\DISPLAY1
          Bounds:
             Top: 0
             Left: 0
             Width: 1920
             Height: 1080

       Display 1:
          Name: SF350_S24F350FH / S24F352FH / S24F354FH (HDMI)
          DeviceId: \\\\.\\DISPLAY2
          Bounds:
             Top: 0
             Left: 1920
             Width: 1366
             Height: 768

根据屏幕分辨率和左上角的值,显示器0应为SF350_S24F350FH/S24F352FH/S24F354FH HDMI,以及为什么与显示器1交换?

这取决于将哪个显示器定义为主显示器。每个监视器的位置都无关紧要


如果您愿意,这个库可以很好地完成这项工作:

根据

要获取显示器上的信息,请首先调用 lpDevice设置为NULL的EnumDisplayDevices。然后打电话 将lpDevice设置为的EnumDisplayDevices 显示从第一次调用到的\u DEVICE.DeviceName iDevNum设置为零的EnumDisplayDevices和。然后 DISPLAY_DEVICE.DeviceString是监视器名称

样本:

private static void QueryDisplayDevices()
{
    DISPLAY_DEVICE device = new DISPLAY_DEVICE();
    device.Initialize();
    uint DispNum = 0;
    while (EnumDisplayDevices(null, DispNum, ref device, 0))
    {
        DISPLAY_DEVICE dev = new DISPLAY_DEVICE();
        dev.Initialize();
        if (EnumDisplayDevices(device.DeviceName, 0, ref dev, 0))
       {
            Console.WriteLine("Device Name:" + dev.DeviceName);
            Console.WriteLine("Monitor name:" + dev.DeviceString);
       }
       DispNum++;
       device.Initialize();
    }
}
根据@Dmo的线索,我使用


它生成正确的监视器名称和设置对!是的,我想是的。这意味着GetMonitorInfo和EnumDisplayDevices之间存在不一致性。GetMonitorInfo将\\\\.\\DISPLAY1视为1920x1080设备外部显示器,但EnumDisplayDevices将\\\\\.\\DISPLAY1视为通用PnP监视器内部显示器。将使用相同的代码尝试该库,并设置与要测试的相同的显示设置。无法复制,请始终按照正确对应的显示设置中的索引顺序返回。我已将EnumDisplaySettings添加到您的示例中,但它仍然使用通用PnP监视器作为1920x1080设备,而它应该是1366x768设备
       Display 0:
          Name: Generic PnP Monitor
          DeviceId: \\\\.\\DISPLAY1
          Bounds:
             Top: 0
             Left: 0
             Width: 1920
             Height: 1080

       Display 1:
          Name: SF350_S24F350FH / S24F352FH / S24F354FH (HDMI)
          DeviceId: \\\\.\\DISPLAY2
          Bounds:
             Top: 0
             Left: 1920
             Width: 1366
             Height: 768
private static void QueryDisplayDevices()
{
    DISPLAY_DEVICE device = new DISPLAY_DEVICE();
    device.Initialize();
    uint DispNum = 0;
    while (EnumDisplayDevices(null, DispNum, ref device, 0))
    {
        DISPLAY_DEVICE dev = new DISPLAY_DEVICE();
        dev.Initialize();
        if (EnumDisplayDevices(device.DeviceName, 0, ref dev, 0))
       {
            Console.WriteLine("Device Name:" + dev.DeviceName);
            Console.WriteLine("Monitor name:" + dev.DeviceString);
       }
       DispNum++;
       device.Initialize();
    }
}
            Rectangle rect;
            Display display;

            foreach (PathInfo pi in PathInfo.GetActivePaths())
            {
                if (!pi.TargetsInfo[0].DisplayTarget.IsAvailable) continue;

                rect=System.Windows.Forms.Screen.GetWorkingArea(new Rectangle(pi.Position, pi.Resolution));
                display = new DisplayImpl()
                {
                    _name = string.IsNullOrEmpty(pi.TargetsInfo[0].DisplayTarget.FriendlyName)? "Generic PnP Monitor" : pi.TargetsInfo[0].DisplayTarget.FriendlyName,
                    _deviceId = pi.DisplaySource.DisplayName,
                    _devicePath=pi.TargetsInfo[0].DisplayTarget.DevicePath,
                    _bounds = new Rectangle(pi.Position,pi.Resolution),
                    _workingArea = rect,
                };

                list.Add(display);
            }