如何通过winapi获得监视器的友好名称?

时间:2014-10-16 12:53:01

标签: c# winapi pinvoke

我使用wmi的Win32_DesktopMonitor类。但这不会返回显示器名称。但是当我使用珠穆朗玛峰(Aida64)时,这就向我展示了它。我认为这个应用程序与winapi一起工作。我找到方法 GetMonitorInfo ,但不明白如何使用它来获取监视器名称。

编辑 请原谅我最糟糕的问题。我想用win api知道监视器的朋友名字。我看这个帖子url msdn,但只能用c语言找到解决方案。

enter image description here

左边的图像显示了我要找的内容。右侧的图像显示从GetMonitorInfo检索的设备名称。

2 个答案:

答案 0 :(得分:11)

此程序显示如何使用p / invoke调用GetMonitorInfo,然后提取设备名称。

using System;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
    class Program
    {
        [StructLayout(LayoutKind.Sequential)]
        struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        struct MONITORINFOEX
        {
            public int Size;
            public RECT Monitor;
            public RECT WorkArea;
            public uint Flags;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string DeviceName;
        }

        [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFOEX lpmi);

        delegate bool MonitorEnumDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData);

        [DllImport("user32.dll")]
        static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData);

        static bool MonitorEnumProc(IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData)
        {
            MONITORINFOEX mi = new MONITORINFOEX();
            mi.Size = Marshal.SizeOf(typeof(MONITORINFOEX));
            if (GetMonitorInfo(hMonitor, ref mi))
                Console.WriteLine(mi.DeviceName);
            return true;
        }

        static void Main(string[] args)
        {
            EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, MonitorEnumProc, IntPtr.Zero);
        }
    }
}

根据您的更新,GetMonitorInfo不会提供您需要的信息。这个程序基于QueryDisplayConfig。请注意,Windows 7中引入了QueryDisplayConfig

using System;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace ConsoleApplication3
{
    class Program
    {
        public const int ERROR_SUCCESS = 0;

        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
        }

        [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;
            DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY   outputTechnology;
            DISPLAYCONFIG_ROTATION                  rotation;
            DISPLAYCONFIG_SCALING                   scaling;
            DISPLAYCONFIG_RATIONAL                  refreshRate;
            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
        {
            int x;
            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;
        }

        [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
        );

        public static string MonitorFriendlyName(LUID adapterId, uint targetId)
        {
            DISPLAYCONFIG_TARGET_DEVICE_NAME deviceName = new DISPLAYCONFIG_TARGET_DEVICE_NAME();
            deviceName.header.size = (uint)Marshal.SizeOf(typeof(DISPLAYCONFIG_TARGET_DEVICE_NAME));
            deviceName.header.adapterId = adapterId;
            deviceName.header.id = targetId;
            deviceName.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
            int error = DisplayConfigGetDeviceInfo(ref deviceName);
            if (error != ERROR_SUCCESS)
                throw new Win32Exception(error);
            return deviceName.monitorFriendlyDeviceName;
        }

        static void Main(string[] args)
        {
            uint PathCount, ModeCount;
            int error = GetDisplayConfigBufferSizes(QUERY_DEVICE_CONFIG_FLAGS.QDC_ONLY_ACTIVE_PATHS,
                out PathCount, out ModeCount);
            if (error != ERROR_SUCCESS)
                throw new Win32Exception(error);

            DISPLAYCONFIG_PATH_INFO[] DisplayPaths = new DISPLAYCONFIG_PATH_INFO[PathCount];
            DISPLAYCONFIG_MODE_INFO[] 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 (int i = 0; i < ModeCount; i++) 
            {
                if (DisplayModes[i].infoType == DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_TARGET)
                {
                    Console.WriteLine(MonitorFriendlyName(DisplayModes[i].adapterId, DisplayModes[i].id));
                }
            }
            Console.ReadLine();
        }
    }
}

我根本没有对此进行过广泛的测试,而且存在错误也很合理。它应该可以让你继续前进。

答案 1 :(得分:0)

接受@DavidHeffeman所做的一些PInvoke工作以及我之前所做的一些工作,我已经将本机签名以及一些辅助函数添加到Vanara库中。现在,通过添加他们的NuGet packages,您可以用很少的几行代码来完成这项工作。

using static Vanara.PInvoke.Gdi32;
using static Vanara.PInvoke.User32;
using static Vanara.PInvoke.User32_Gdi;

QueryDisplayConfig(QDC.QDC_ONLY_ACTIVE_PATHS, out var paths, out var modes, out var topId);
foreach (var mode in modes.Where(m => m.infoType == DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_TARGET))
{ 
   Console.WriteLine(DisplayConfigGetDeviceInfo<DISPLAYCONFIG_TARGET_DEVICE_NAME>(mode.adapterId, mode.id).monitorFriendlyDeviceName);
}