windows 如何获得实际的监视器名称?如分辨率对话框中所示
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4958683/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I get the actual Monitor name? as seen in the resolution dialog
提问by JamesStuddart
I am trying to grab the friendly name for the monitors on my system. I am using C#.
我正在尝试获取系统上监视器的友好名称。我正在使用 C#。
I have tried Screen
, which just gives me //./DisplayXX
. I have also tried both Win32_DesktopMonitor
and EnumDisplayDevices
, they all give me variations of //./DisplayXX
OR Generic Monitor
, whereas I know my displays names are SyncMaster
and SM2333T
.
我试过了Screen
,这只是给了我//./DisplayXX
。我也试过Win32_DesktopMonitor
and EnumDisplayDevices
,它们都给了我//./DisplayXX
OR 的变体Generic Monitor
,而我知道我的显示名称是SyncMaster
and SM2333T
。
Now Windows knows what these monitors are, displays them in the Devices and Printerswindows with the correct names, and also in the dialog for setting location and resolution.
现在 Windows 知道这些显示器是什么,在设备和打印机窗口中以正确的名称显示它们,还在用于设置位置和分辨率的对话框中显示。
Where can I grab these names from? I have looked in the registry and cant seem to find them, so any help will be great.
我可以从哪里获取这些名称?我查看了注册表,似乎找不到它们,因此任何帮助都会很棒。
SOLUTION:The issue I had was when calling EnumDisplayDevices
the second time I was setting iDevNum
to id again, which meant I was trying to grab data from the wrong place, I then replaced this with 0, and it works perfectly, see below for the code.
解决方案:我遇到的问题是EnumDisplayDevices
第二次调用时我iDevNum
再次设置为 id,这意味着我试图从错误的位置获取数据,然后我将其替换为 0,并且它运行良好,请参阅下面的代码。
var device = new DISPLAY_DEVICE();
device.cb = Marshal.SizeOf(device);
try
{
for (uint id = 0; EnumDisplayDevices(null, id, ref device, 0); id++)
{
Console.WriteLine(String.Format("{0}, {1}, {2}, {3}, {4}, {5}", id, device.DeviceName, device.DeviceString, device.StateFlags, device.DeviceID, device.DeviceKey));
Console.WriteLine();
device.cb = Marshal.SizeOf(device);
EnumDisplayDevices(device.DeviceName, 0, ref device, 0);
Console.WriteLine(String.Format("{0}, {1}, {2}, {3}, {4}, {5}", id, device.DeviceName, device.DeviceString, device.StateFlags, device.DeviceID, device.DeviceKey));
device.cb = Marshal.SizeOf(device);
device.cb = Marshal.SizeOf(device);
return;
}
}
}
catch (Exception ex)
{
Console.WriteLine(String.Format("{0}", ex.ToString()));
}
采纳答案by Sertac Akyuz
After you get a DisplayDevice.DeviceName
like //./DisplayX
from EnumDisplayDevices
, you are supposed to call 'EnumDisplayDevices' a second time, this time providing the 'DisplayDevice.DeviceName' that you got from the previous call as lpDevice
, and '0' as iDevNum
. Then you'll have the monitor name in DisplayDevice.DeviceString
.
当你得到一个DisplayDevice.DeviceName
像//./DisplayX
从EnumDisplayDevices
,你应该调用“EnumDisplayDevices”第二次,这次提供“DisplayDevice.DeviceName”你从以前的调用作为了lpDevice
,和“0”的iDevNum
。然后您将在DisplayDevice.DeviceString
.
回答by G.Y
Examine carefully! this is what you looking for,
you can now write Screen.PrimaryScreen.DeviceFriendlyName()
and get the real name of the monitor device.
(and yes, it is the same name seen in resolution dialog)
仔细检查!这就是您要找的,您现在可以编写Screen.PrimaryScreen.DeviceFriendlyName()
并获取监控设备的真实名称。
(是的,它与分辨率对话框中看到的名称相同)
While I did add some personal touch to wrap this code I did not create the Hard-Core part of it, And so I would like to thank 2 developers, The MS developer who gave the essentials in C++ and the anonymous developer who translated those essentials to C# code.
虽然我确实添加了一些个人风格来包装这段代码,但我没有创建它的硬核部分,所以我要感谢 2 位开发人员,在 C++ 中提供基本要素的 MS 开发人员和翻译这些基本要素的匿名开发人员到 C# 代码。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Tools;
namespace ConsoleApplication35
{
internal class Program
{
private static void Main()
{
Console.WriteLine(Screen.PrimaryScreen.DeviceFriendlyName());
//output: ASUS MK241
Console.ReadLine();
}
}
}
namespace Tools
{
public static class ScreenInterrogatory
{
public const int ERROR_SUCCESS = 0;
#region enums
public enum QUERY_DEVICE_CONFIG_FLAGS : uint
{
QDC_ALL_PATHS = 0x00000001,
QDC_ONLY_ACTIVE_PATHS = 0x00000002,
QDC_DATABASE_CURRENT = 0x00000004
}
public enum DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY : uint
{
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER = 0xFFFFFFFF,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15 = 0,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SVIDEO = 1,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPOSITE_VIDEO = 2,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPONENT_VIDEO = 3,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI = 4,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI = 5,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_LVDS = 6,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_D_JPN = 8,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDI = 9,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL = 10,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED = 11,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EXTERNAL = 12,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED = 13,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDTVDONGLE = 14,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_MIRACAST = 15,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL = 0x80000000,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_FORCE_UINT32 = 0xFFFFFFFF
}
public enum DISPLAYCONFIG_SCANLINE_ORDERING : uint
{
DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED = 0,
DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE = 1,
DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED = 2,
DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_UPPERFIELDFIRST = DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED,
DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_LOWERFIELDFIRST = 3,
DISPLAYCONFIG_SCANLINE_ORDERING_FORCE_UINT32 = 0xFFFFFFFF
}
public enum DISPLAYCONFIG_ROTATION : uint
{
DISPLAYCONFIG_ROTATION_IDENTITY = 1,
DISPLAYCONFIG_ROTATION_ROTATE90 = 2,
DISPLAYCONFIG_ROTATION_ROTATE180 = 3,
DISPLAYCONFIG_ROTATION_ROTATE270 = 4,
DISPLAYCONFIG_ROTATION_FORCE_UINT32 = 0xFFFFFFFF
}
public enum DISPLAYCONFIG_SCALING : uint
{
DISPLAYCONFIG_SCALING_IDENTITY = 1,
DISPLAYCONFIG_SCALING_CENTERED = 2,
DISPLAYCONFIG_SCALING_STRETCHED = 3,
DISPLAYCONFIG_SCALING_ASPECTRATIOCENTEREDMAX = 4,
DISPLAYCONFIG_SCALING_CUSTOM = 5,
DISPLAYCONFIG_SCALING_PREFERRED = 128,
DISPLAYCONFIG_SCALING_FORCE_UINT32 = 0xFFFFFFFF
}
public enum DISPLAYCONFIG_PIXELFORMAT : uint
{
DISPLAYCONFIG_PIXELFORMAT_8BPP = 1,
DISPLAYCONFIG_PIXELFORMAT_16BPP = 2,
DISPLAYCONFIG_PIXELFORMAT_24BPP = 3,
DISPLAYCONFIG_PIXELFORMAT_32BPP = 4,
DISPLAYCONFIG_PIXELFORMAT_NONGDI = 5,
DISPLAYCONFIG_PIXELFORMAT_FORCE_UINT32 = 0xffffffff
}
public enum DISPLAYCONFIG_MODE_INFO_TYPE : uint
{
DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE = 1,
DISPLAYCONFIG_MODE_INFO_TYPE_TARGET = 2,
DISPLAYCONFIG_MODE_INFO_TYPE_FORCE_UINT32 = 0xFFFFFFFF
}
public enum DISPLAYCONFIG_DEVICE_INFO_TYPE : uint
{
DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME = 1,
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME = 2,
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE = 3,
DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME = 4,
DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_PERSISTENCE = 5,
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_BASE_TYPE = 6,
DISPLAYCONFIG_DEVICE_INFO_FORCE_UINT32 = 0xFFFFFFFF
}
#endregion
#region structs
[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
public uint LowPart;
public int HighPart;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_PATH_SOURCE_INFO
{
public LUID adapterId;
public uint id;
public uint modeInfoIdx;
public uint statusFlags;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_PATH_TARGET_INFO
{
public LUID adapterId;
public uint id;
public uint modeInfoIdx;
private DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology;
private DISPLAYCONFIG_ROTATION rotation;
private DISPLAYCONFIG_SCALING scaling;
private DISPLAYCONFIG_RATIONAL refreshRate;
private DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;
public bool targetAvailable;
public uint statusFlags;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_RATIONAL
{
public uint Numerator;
public uint Denominator;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_PATH_INFO
{
public DISPLAYCONFIG_PATH_SOURCE_INFO sourceInfo;
public DISPLAYCONFIG_PATH_TARGET_INFO targetInfo;
public uint flags;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_2DREGION
{
public uint cx;
public uint cy;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_VIDEO_SIGNAL_INFO
{
public ulong pixelRate;
public DISPLAYCONFIG_RATIONAL hSyncFreq;
public DISPLAYCONFIG_RATIONAL vSyncFreq;
public DISPLAYCONFIG_2DREGION activeSize;
public DISPLAYCONFIG_2DREGION totalSize;
public uint videoStandard;
public DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_TARGET_MODE
{
public DISPLAYCONFIG_VIDEO_SIGNAL_INFO targetVideoSignalInfo;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINTL
{
private int x;
private int y;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_SOURCE_MODE
{
public uint width;
public uint height;
public DISPLAYCONFIG_PIXELFORMAT pixelFormat;
public POINTL position;
}
[StructLayout(LayoutKind.Explicit)]
public struct DISPLAYCONFIG_MODE_INFO_UNION
{
[FieldOffset(0)]
public DISPLAYCONFIG_TARGET_MODE targetMode;
[FieldOffset(0)]
public DISPLAYCONFIG_SOURCE_MODE sourceMode;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_MODE_INFO
{
public DISPLAYCONFIG_MODE_INFO_TYPE infoType;
public uint id;
public LUID adapterId;
public DISPLAYCONFIG_MODE_INFO_UNION modeInfo;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS
{
public uint value;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_DEVICE_INFO_HEADER
{
public DISPLAYCONFIG_DEVICE_INFO_TYPE type;
public uint size;
public LUID adapterId;
public uint id;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct DISPLAYCONFIG_TARGET_DEVICE_NAME
{
public DISPLAYCONFIG_DEVICE_INFO_HEADER header;
public DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS flags;
public DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology;
public ushort edidManufactureId;
public ushort edidProductCodeId;
public uint connectorInstance;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
public string monitorFriendlyDeviceName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string monitorDevicePath;
}
#endregion
#region DLL-Imports
[DllImport("user32.dll")]
public static extern int GetDisplayConfigBufferSizes(
QUERY_DEVICE_CONFIG_FLAGS flags, out uint numPathArrayElements, out uint numModeInfoArrayElements);
[DllImport("user32.dll")]
public static extern int QueryDisplayConfig(
QUERY_DEVICE_CONFIG_FLAGS flags,
ref uint numPathArrayElements, [Out] DISPLAYCONFIG_PATH_INFO[] PathInfoArray,
ref uint numModeInfoArrayElements, [Out] DISPLAYCONFIG_MODE_INFO[] ModeInfoArray,
IntPtr currentTopologyId
);
[DllImport("user32.dll")]
public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_TARGET_DEVICE_NAME deviceName);
#endregion
private static string MonitorFriendlyName(LUID adapterId, uint targetId)
{
var deviceName = new DISPLAYCONFIG_TARGET_DEVICE_NAME
{
header =
{
size = (uint)Marshal.SizeOf(typeof (DISPLAYCONFIG_TARGET_DEVICE_NAME)),
adapterId = adapterId,
id = targetId,
type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME
}
};
var error = DisplayConfigGetDeviceInfo(ref deviceName);
if (error != ERROR_SUCCESS)
throw new Win32Exception(error);
return deviceName.monitorFriendlyDeviceName;
}
private static IEnumerable<string> GetAllMonitorsFriendlyNames()
{
uint pathCount, modeCount;
var error = GetDisplayConfigBufferSizes(QUERY_DEVICE_CONFIG_FLAGS.QDC_ONLY_ACTIVE_PATHS, out pathCount, out modeCount);
if (error != ERROR_SUCCESS)
throw new Win32Exception(error);
var displayPaths = new DISPLAYCONFIG_PATH_INFO[pathCount];
var displayModes = new DISPLAYCONFIG_MODE_INFO[modeCount];
error = QueryDisplayConfig(QUERY_DEVICE_CONFIG_FLAGS.QDC_ONLY_ACTIVE_PATHS,
ref pathCount, displayPaths, ref modeCount, displayModes, IntPtr.Zero);
if (error != ERROR_SUCCESS)
throw new Win32Exception(error);
for (var i = 0; i < modeCount; i++)
if (displayModes[i].infoType == DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_TARGET)
yield return MonitorFriendlyName(displayModes[i].adapterId, displayModes[i].id);
}
public static string DeviceFriendlyName(this Screen screen)
{
var allFriendlyNames = GetAllMonitorsFriendlyNames();
for (var index = 0; index < Screen.AllScreens.Length; index++)
if (Equals(screen, Screen.AllScreens[index]))
return allFriendlyNames.ToArray()[index];
return null;
}
}
}
回答by Luke
This information is almost certainly obtained through the SetupAPIfamily of functions. I don't recall the specifics off the top of my head, but you will need to get all monitor devices (GUID_DEVINTERFACE_MONITOR) and obtain their friendly names (SPDRP_FRIENDLYNAME).
该信息几乎可以肯定是通过SetupAPI系列函数获得的。我不记得具体细节,但您需要获取所有监控设备 (GUID_DEVINTERFACE_MONITOR) 并获取它们的友好名称 (SPDRP_FRIENDLYNAME)。
回答by Soroush Falahati
From here: Get Exact Monitor/Display/Screen Name
从这里:获取确切的监视器/显示/屏幕名称
Well, this question is old, however, as for the sake of google redirects, I suggest my 'WindowsDisplayAPI' library.
好吧,这个问题很旧,但是,为了谷歌重定向,我建议使用我的“WindowsDisplayAPI”库。
https://www.nuget.org/packages/WindowsDisplayAPI
https://www.nuget.org/packages/WindowsDisplayAPI
Using the library, there are multiple ways to get the display name. The simplest way is:
使用库,有多种方法可以获取显示名称。最简单的方法是:
foreach (var display in Display.GetDisplays())
{
Console.WriteLine(display.DeviceName);
}
But this is using the old API, if you are sure that your program targets at least Windows Vista, I suggest the following code:
但这是使用旧 API,如果您确定您的程序至少针对 Windows Vista,我建议使用以下代码:
foreach (var target in DisplayConfig.PathDisplayTarget.GetDisplayTargets())
{
Console.WriteLine(target.FriendlyName);
}
回答by user2297042
I have been seraching for an answer to this same question. In this linkit is mentioned that generic pnp monitor is shown, because there is no driver installed for the monitor and the device is running with the Generic PnP Monitor Driver.
我一直在寻找同样问题的答案。在此链接中提到显示了通用 pnp 监视器,因为没有为监视器安装驱动程序,并且设备正在使用通用 PnP 监视器驱动程序运行。
For windows 7 and higher there seems to be a different function than EnumDisplayDevices to get the desired display names as shown in the control panel. This can be done with the DisplayConfigGetDeviceInfo function as explained here. I hope someone soon can translate this to Delphi, which I am looking for.
对于 Windows 7 及更高版本,似乎有一个与 EnumDisplayDevices 不同的功能来获取控制面板中显示的所需显示名称。这可以通过DisplayConfigGetDeviceInfo函数来完成作为解释在这里。我希望很快有人可以将其翻译成我正在寻找的 Delphi。