Doug Null
Doug Null

Reputation: 8327

C# EnumDisplaySettings not working for lpszDeviceName

EnumDisplaySettings() works if its IpszDeviceName argument is null, but returns 0 if it's a device name.

Here's the output of the code below.

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. <<<<<<<<<<<<<<

And here's the source code.

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

Upvotes: 2

Views: 4447

Answers (1)

Dan Chenier
Dan Chenier

Reputation: 179

You need to convert the lpDisplayDevice.DeviceName to a byte array that the EnumDisplaySettings function understands. That's best done with an extension method on the String class:

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;
    }
}

Then, change the signature of the EnumDisplaySettings extern declaration to be take in a byte array for the 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);

Then, you can call EnumDisplaySettings like so:

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

Upvotes: 4

Related Questions