【问题标题】:C# EnumDisplaySettings not working for lpszDeviceNameC# EnumDisplaySettings 不适用于 lpszDeviceName
【发布时间】:2013-04-25 02:50:37
【问题描述】:

如果其 IpszDeviceName 参数为 null,则 EnumDisplaySettings() 有效,但如果它是设备名称,则返回 0。

这是下面代码的输出。

devNum =0

cb =424

DeviceID =PCI\VEN_10DE&DEV_0402&SUBSYS_0440196E&REV_A1

DeviceKey =\Registry\Machine\System\CurrentControlSet\Control\Video\{B757E378-AF2E-4826-BA9E-927C5B81B139}\0000

DeviceName =\\.\DISPLAY1

DeviceString =NVIDIA GeForce 8600 GT

Monitor name =Generic PnP Monitor

>>> EnumDisplaySettings RETURNED 0. <<<<<<<<<<<<<<

devNum =1

cb =424

DeviceID =PCI\VEN_10DE&DEV_0402&SUBSYS_0440196E&REV_A1

DeviceKey =\Registry\Machine\System\CurrentControlSet\Control\Video\{B757E378-AF2E-4826-BA9E-927C5B81B139}\0001

DeviceName =\\.\DISPLAY2

DeviceString =NVIDIA GeForce 8600 GT

Monitor name =Generic PnP Monitor

>>> EnumDisplaySettings RETURNED 0. <<<<<<<<<<<<<<

这里是源代码。

        public static void show_display_devices()
    {
        DISPLAY_DEVICE lpDisplayDevice = new DISPLAY_DEVICE(0);     // OUT
            DISPLAY_DEVICE monitor_name = new DISPLAY_DEVICE(0);        // OUT
        DEVMODE mode = new DEVMODE();

        int devNum = 0;
        while (EnumDisplayDevices(null, devNum, ref lpDisplayDevice, 0))
        {

            Console.WriteLine("\ndevNum =" + devNum);
            Console.WriteLine("cb =" + lpDisplayDevice.cb);
            Console.WriteLine("DeviceID =" + lpDisplayDevice.DeviceID);
            Console.WriteLine("DeviceKey =" + lpDisplayDevice.DeviceKey);
            Console.WriteLine("DeviceName =" + lpDisplayDevice.DeviceName.Trim());
            Console.WriteLine("DeviceString =" + lpDisplayDevice.DeviceString.Trim());
            // Show monitor name:



            EnumDisplayDevices( lpDisplayDevice.DeviceName, 0, ref monitor_name, 0);
            Console.WriteLine("Monitor name =" + monitor_name.DeviceString.Trim());

            // Show the device's settings:
            if (EnumDisplaySettings(lpDisplayDevice.DeviceName,
                    ENUM_CURRENT_SETTINGS,
                    ref mode) == true) // Succeeded
            {
                Console.WriteLine("Current Mode:\n\t" +
                    "{0} by {1}, " +
                    "{2} bit, " +
                    "{3} degrees, " +
                    "{4} hertz",
                    mode.dmPelsWidth,
                    mode.dmPelsHeight,
                    mode.dmBitsPerPel,
                    mode.dmDisplayOrientation * 90,
                    mode.dmDisplayFrequency);
            }
            else
            {
                Console.WriteLine(">>>  EnumDisplaySettings  RETURNED 0.  <<<<<<<<<<<<<<");
            }
            ++devNum;
        }
    }

    [DllImport("User32.dll")]
    private static extern bool EnumDisplayDevices(
        string lpDevice, int iDevNum,
        ref DISPLAY_DEVICE lpDisplayDevice, int dwFlags);


          [DllImport("User32.dll", SetLastError=true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern Boolean EnumDisplaySettings(
        [param: MarshalAs(UnmanagedType.LPTStr)]
        string lpszDeviceName,
        [param: MarshalAs(UnmanagedType.U4)]
        int iModeNum,
        [In, Out]
        ref DEVMODE lpDevMode);

【问题讨论】:

  • 这意味着它失败了。您忘记了 pinvoke 声明中的 SetLastError 属性并调用 Marshal.GetLastWin32Error() 来检索错误代码。
  • Hans Passant:你有例子吗?
  • 汉斯:谢谢。我更正了声明。返回的错误码是6。

标签: c# windows


【解决方案1】:

您需要将 lpDisplayDevice.DeviceName 转换为 EnumDisplaySettings 函数可以理解的字节数组。最好在 String 类上使用 extension method

public static class StringExtensions
{
    public static byte[] ToLPTStr(this string str)
    {
        var lptArray = new byte[str.Length+1];

        var index = 0;
        foreach (char c in str.ToCharArray())
            lptArray[index++] = Convert.ToByte(c);

        lptArray[index] = Convert.ToByte('\0');

        return lptArray;
    }
}

然后,将 EnumDisplaySettings extern 声明的签名更改为接受 lpszDeviceName 的字节数组:

    [DllImport("User32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    internal static extern Boolean EnumDisplaySettings(
        byte[] lpszDeviceName,
        [param: MarshalAs(UnmanagedType.U4)]
        int iModeNum,
         [In, Out]
        ref DEVMODE lpDevMode);

然后,您可以像这样调用 EnumDisplaySettings:

EnumDisplayDevices(lpDisplayDevice.DeviceName.ToLPTStr(), 0, ref monitor_name, 0);

【讨论】:

  • 就我而言,只需添加 CharSet = CharSet.Unicode 即可解决问题。
猜你喜欢
  • 2017-12-03
  • 1970-01-01
  • 2012-03-09
  • 1970-01-01
  • 2017-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多