监视器(显示器)名称和边界

3
我的应用程序具有使用双显示器配置的能力。在应用程序的设置中,我列出了可用的显示器,用户将选择他的第二个屏幕。
我正在使用以下方式获取(真实)监视器设备名称:

http://msdn.microsoft.com/en-us/library/aa394122%28VS.85%29.aspx

    SelectQuery q = new SelectQuery("SELECT Name, DeviceID, ScreenHeight, ScreenWidth FROM Win32_DesktopMonitor");
 using (ManagementObjectSearcher mos = new ManagementObjectSearcher(q))
            {
                foreach (ManagementObject mo in mos.Get())
                {
                       ...
                }
             }

但我还需要显示边界(顶部、左侧等),而这个方法并没有给我。但是 System.Windows.Forms.Screen 可以给我边界,但不能给出真实的设备名称。如果我确信它们每次都能按照相同的顺序返回设备,我可以将它们结合使用。这两个方法每次都会按照时间顺序返回“Device 1”、“Device 2”等吗?还是有一种包含我所需所有信息的方法?
[编辑] Win32_DesktopMonitor 没有给我我的第二个监视器的名称。它只是称它为默认监视器。而且它把它列在我的主监视器之前。
[编辑2] 好吧,它把名称和分辨率搞混了...... 有人知道这里出了什么问题吗?

到底是什么出了问题? - Gabe
Win32_DesktopMonitor没有返回我的副显示器的正确名称,分辨率也被交换了。 - bwoogie
实际上,如果您查看有关Win32_DesktopMonitor的MSDN页面,它指出:“从Windows Vista开始,与Windows显示驱动程序模型(WDDM)不兼容的硬件会返回此类实例的不准确属性值。” - Mark Hall
嗯,我非常确定它们是兼容的。它们在显示控制面板中正确显示。 - bwoogie
1个回答

1

我以前使用Win API调用完成过这个任务。我在下面粘贴了一些代码片段,可能对你有帮助...

public void Store()
{
  Screens.Clear();
  uint iAdaptorNum = 0;
  Win.User32.DISPLAY_DEVICE adaptor = new Win.User32.DISPLAY_DEVICE();
        adaptor.cb = (short)Marshal.SizeOf(adaptor);
  Win.User32.DISPLAY_DEVICE dd = new Win.User32.DISPLAY_DEVICE();
  dd.cb = (short)Marshal.SizeOf(dd);

  while (Win.User32.EnumDisplayDevices(null, iAdaptorNum, ref adaptor, Win.User32.EDD_GET_DEVICE_INTERFACE_NAME))
  {
    uint iDevNum = 0;
    while (Win.User32.EnumDisplayDevices(adaptor.DeviceName, iDevNum, ref dd, Win.User32.EDD_GET_DEVICE_INTERFACE_NAME))
    {
      log.WriteFormat(LogLevel.Debug, "Adaptor {0}:{1} {2}='{3}', Device {4}='{5}', State flags = {4}",
        iAdaptorNum, iDevNum, adaptor.DeviceName, adaptor.DeviceString, dd.DeviceName, dd.DeviceString, dd.StateFlags);
      if ((dd.StateFlags & Win.User32.DisplayDeviceStateFlags.AttachedToDesktop) > 0)
        Screens.Add(new ScreenInfo(adaptor, dd));
      iDevNum++;
    }
    iAdaptorNum++;
  }
}

这就是在new ScreenInfo后面调用的内容:

public void StoreScreen(Win.User32.DISPLAY_DEVICE Adaptor, Win.User32.DISPLAY_DEVICE Device)
    {
  adaptor = Adaptor.DeviceName;
  device = Device.DeviceName;
  name = string.Format("{0} on {1}", Device.DeviceString, Adaptor.DeviceString);
  Win.User32.DEVMODE dm = newDevMode();
  if (Win.User32.EnumDisplaySettings(Adaptor.DeviceName, Win.User32.ENUM_CURRENT_SETTINGS, ref dm) != 0)
  {
    isAttached = (Adaptor.StateFlags & Win.User32.DisplayDeviceStateFlags.AttachedToDesktop) > 0;
    isPrimary = (Adaptor.StateFlags & Win.User32.DisplayDeviceStateFlags.PrimaryDevice) > 0;
    mode = findMode(Adaptor.DeviceName, dm);
    if ((dm.dmFields & Win.User32.DM.PelsWidth) > 0) width = dm.dmPelsWidth;
    if ((dm.dmFields & Win.User32.DM.PelsHeight) > 0) height = dm.dmPelsHeight;
    if ((dm.dmFields & Win.User32.DM.BitsPerPixel) > 0) bpp = dm.dmBitsPerPel;
    if ((dm.dmFields & Win.User32.DM.Orientation) > 0) orientation = dm.dmOrientation;
    if ((dm.dmFields & Win.User32.DM.DisplayFrequency) > 0) frequency = dm.dmDisplayFrequency;
    if ((dm.dmFields & Win.User32.DM.DisplayFlags) > 0) flags = dm.dmDisplayFlags;
    if ((dm.dmFields & Win.User32.DM.Position) > 0)
    {
      posX = dm.dmPosition.x;
      posY = dm.dmPosition.y;
    }
  }
}

private static Win.User32.DEVMODE newDevMode()
{
  Win.User32.DEVMODE dm = new Win.User32.DEVMODE();
  dm.dmDeviceName = new String(new char[31]);
  dm.dmFormName = new String(new char[31]);
  dm.dmSize = (short)Marshal.SizeOf(dm);
  return dm;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接