All display devices return with default values and ID == 0 in QueryDisplayConfig

0

I'm trying to set-up an easy 1-click change of the connection of my screens (extended <--> disconnected) but my screens are assigned no ID by the QueryDisplayConfig method, despite being filtered by what I pass as flags QDC_ONLY_ACTIVE_PATHS

(I'm using the User32 PInvoke lib from https://github.com/AArnott/pinvoke, in addition to what you can find in the code below)

I tried stepping through the code with breakpoints, made sure EVERY value is the default value and it's not just a typo I made, tried elevating VS to run as administrator.

Also made extra sure that the flags and errors are functioning correctly.

If I change the "id" value to 0, it pops errors (87 - Wrong Parameters)

If I change it to 1, it displays 73 devices without Errors

and if I change it to 2 or 4 it displays the amount of my connected devices without Errors.

-- Tried enabling/disabling the devices in runtime, and it updated successfully, so we can safely assume that there's no error on the filtering part.

[DllImport("User32.dll")]
public static extern int GetDisplayConfigBufferSizes(uint flags, ref uint numPathArrayElements, ref uint numModeInfoArrayElements);
[DllImport("User32.dll")]
public static extern int QueryDisplayConfig(
    uint flags,
    ref uint numPathArrayElements, DISPLAYCONFIG_PATH_INFO[] pathArray,
    ref uint numModeInfoArrayElements, DISPLAYCONFIG_MODE_INFO[] modeInfoArray,
    DISPLAYCONFIG_TOPOLOGY_ID[] currentTopologyId
);
[DllImport("User32.dll")]
public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_DEVICE_INFO_HEADER requestPacket);
[DllImport("User32.dll")]
public static extern int SetDisplayConfig(
    uint numPathArrayElements, DISPLAYCONFIG_PATH_INFO[] pathArray,
    uint numModeInfoArrayElements, DISPLAYCONFIG_MODE_INFO[] modeInfoArray,
    uint flags
);

    // QDC_ALL_PATHS == 0x00000001
    // QDC_ONLY_ACTIVE_PATHS == 0x00000002
    // QDC_DATABASE_CURRENT == 0x00000004

public static void CheckDisplays() {
    uint numPathArrayElements = 0;
    uint numModeInfoArrayElements = 0;
    uint id = 2; // QDC_ONLY_ACTIVE_PATHS

    int bufferError = GetDisplayConfigBufferSizes(id, ref numPathArrayElements, ref numModeInfoArrayElements);

    DISPLAYCONFIG_PATH_INFO[] pathArray = new DISPLAYCONFIG_PATH_INFO[numPathArrayElements];
    DISPLAYCONFIG_MODE_INFO[] modeArray = new DISPLAYCONFIG_MODE_INFO[numModeInfoArrayElements];

    int queryError = QueryDisplayConfig(id, ref numPathArrayElements, pathArray, ref numModeInfoArrayElements, modeArray, null);

    Console.WriteLine();
    Console.WriteLine("Elements: " + numPathArrayElements); // Prints the correct amount of connected screens.
    Console.WriteLine("BUFFER ERROR: " + bufferError);      // Prints 0 -- as in Success.
    Console.WriteLine("PATH ERROR: " + queryError);         // Prints 0 -- as in Success.

    for (int i = 0; i < pathArray.Length; i++) {
        bool isScreenDisplayingCorrectly = pathArray[i].flags != 0 || pathArray[i].targetInfo.refreshRate.Denominator != 0 || 
            pathArray[i].sourceInfo.id != 0 || pathArray[i].sourceInfo.modeInfoIdx != 0;
        if (isScreenDisplayingCorrectly) { Console.WriteLine($"Screen{i} is not displayed as empty!"); }
        // Everything has default values and IDs of 0.. Nothing prints here.
    }
}

Each screen should be assigned an ID and a proper mode.

Instead, everything has the default value and I seem to be stuck.

c#
pinvoke
windows-api-code-pack
asked on Stack Overflow Jul 17, 2019 by Lyrcxis

1 Answer

0

Your declaration for QueryDisplayConfig is wrong : arrays must be [Out]

This works for me :

(I have only 1 monitor but the values received in arrays are the same as in C++ (I translated structures from SDK headers))

(IntPtr.Zero for currentTopologyId with QDC_ONLY_ACTIVE_PATHS)

    [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern int QueryDisplayConfig(uint flags, ref uint numPathArrayElements, [Out] DISPLAYCONFIG_PATH_INFO[] pathArray,
        ref uint modeInfoArrayElements, [Out] DISPLAYCONFIG_MODE_INFO[] modeInfoArray, IntPtr currentTopologyId);
answered on Stack Overflow Jul 18, 2019 by Castorix • edited Jul 18, 2019 by Castorix

User contributions licensed under CC BY-SA 3.0