Vanara/PInvoke/User32/WinUser.Display.cs

1096 lines
60 KiB
C#

using System;
using System.Runtime.InteropServices;
using Vanara.Extensions;
using Vanara.InteropServices;
using static Vanara.PInvoke.Gdi32;
namespace Vanara.PInvoke
{
public static partial class User32
{
/// <summary>The type of information to retrieve.</summary>
[PInvokeData("wingdi.h", MSDNShortId = "5ec7f521-28b5-4922-a3fc-aa4433de69e0")]
[Flags]
public enum QDC
{
/// <summary>The caller requests the table sizes to hold all the possible path combinations.</summary>
QDC_ALL_PATHS = 0x00000001,
/// <summary>The caller requests the table sizes to hold only active paths.</summary>
QDC_ONLY_ACTIVE_PATHS = 0x00000002,
/// <summary>
/// The caller requests the table sizes to hold the active paths as defined in the persistence database for the currently
/// connected monitors.
/// </summary>
QDC_DATABASE_CURRENT = 0x00000004,
/// <summary>Undocumented.</summary>
QDC_VIRTUAL_MODE_AWARE = 0x00000010,
/// <summary>Undocumented.</summary>
QDC_INCLUDE_HMD = 0x00000020,
}
/// <summary>Flag values that indicates the behavior of SetDisplayConfig.</summary>
[PInvokeData("wingdi.h", MSDNShortId = "9f649fa0-ffb2-44c6-9a66-049f888e3b04")]
[Flags]
public enum SDC
{
/// <summary>The caller requests the last internal configuration from the persistence database.</summary>
SDC_TOPOLOGY_INTERNAL = 0x00000001,
/// <summary>The caller requests the last clone configuration from the persistence database.</summary>
SDC_TOPOLOGY_CLONE = 0x00000002,
/// <summary>The caller requests the last extended configuration from the persistence database.</summary>
SDC_TOPOLOGY_EXTEND = 0x00000004,
/// <summary>The caller requests the last external configuration from the persistence database.</summary>
SDC_TOPOLOGY_EXTERNAL = 0x00000008,
/// <summary>
/// The caller provides the path data so the function only queries the persistence database to find and use the source and target mode.
/// </summary>
SDC_TOPOLOGY_SUPPLIED = 0x00000010,
/// <summary>
/// The caller requests a combination of all four SDC_TOPOLOGY_XXX configurations. This value informs the API to set the last
/// known display configuration for the current connected monitors.
/// </summary>
SDC_USE_DATABASE_CURRENT = SDC_TOPOLOGY_INTERNAL | SDC_TOPOLOGY_CLONE | SDC_TOPOLOGY_EXTEND | SDC_TOPOLOGY_EXTERNAL,
/// <summary>
/// The topology, source, and target mode information that are supplied in the pathArray and the modeInfoArray parameters are
/// used, rather than looking up the configuration in the database.
/// </summary>
SDC_USE_SUPPLIED_DISPLAY_CONFIG = 0x00000020,
/// <summary>
/// The system tests for the requested topology, source, and target mode information to determine whether it can be set.
/// </summary>
SDC_VALIDATE = 0x00000040,
/// <summary>The resulting topology, source, and target mode is set.</summary>
SDC_APPLY = 0x00000080,
/// <summary>
/// A modifier to the SDC_APPLY flag. This causes the change mode to be forced all the way down to the driver for each active display.
/// </summary>
SDC_NO_OPTIMIZATION = 0x00000100,
/// <summary>The resulting topology, source, and target mode are saved to the database.</summary>
SDC_SAVE_TO_DATABASE = 0x00000200,
/// <summary>
/// If required, the function can modify the specified source and target mode information in order to create a functional display
/// path set.
/// </summary>
SDC_ALLOW_CHANGES = 0x00000400,
/// <summary>
/// When the function processes a SDC_TOPOLOGY_XXX request, it can force path persistence on a target to satisfy the request if
/// necessary. For information about the other flags that this flag can be combined with, see the following list.
/// </summary>
SDC_PATH_PERSIST_IF_REQUIRED = 0x00000800,
/// <summary>
/// The caller requests that the driver is given an opportunity to update the GDI mode list while SetDisplayConfig sets the new
/// display configuration. This flag value is only valid when the SDC_USE_SUPPLIED_DISPLAY_CONFIG and SDC_APPLY flag values are
/// also specified.
/// </summary>
SDC_FORCE_MODE_ENUMERATION = 0x00001000,
/// <summary>
/// A modifier to the SDC_TOPOLOGY_SUPPLIED flag that indicates that SetDisplayConfig should ignore the path order of the
/// supplied topology when searching the database. When this flag is set, the topology set is the most recent topology that
/// contains all the paths regardless of the path order.
/// </summary>
SDC_ALLOW_PATH_ORDER_CHANGES = 0x00002000,
/// <summary>Undocumented.</summary>
SDC_VIRTUAL_MODE_AWARE = 0x00008000,
}
/// <summary>The <c>DisplayConfigGetDeviceInfo</c> function retrieves display configuration information about the device.</summary>
/// <param name="requestPacket">
/// A pointer to a DISPLAYCONFIG_DEVICE_INFO_HEADER structure. This structure contains information about the request, which includes
/// the packet type in the <c>type</c> member. The type and size of additional data that <c>DisplayConfigGetDeviceInfo</c> returns
/// after the header structure depend on the packet type.
/// </param>
/// <returns>
/// <para>The function returns one of the following return codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function succeeded.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>The combination of parameters and flags specified are invalid.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_SUPPORTED</term>
/// <term>
/// The system is not running a graphics driver that was written according to the Windows Display Driver Model (WDDM). The function
/// is only supported on a system with a WDDM driver running.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The caller does not have access to the console session. This error occurs if the calling process does not have access to the
/// current desktop or is running on a remote session.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INSUFFICIENT_BUFFER</term>
/// <term>The size of the packet that the caller passes is not big enough for the information that the caller requests.</term>
/// </item>
/// <item>
/// <term>ERROR_GEN_FAILURE</term>
/// <term>An unspecified error occurred.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Use the <c>DisplayConfigGetDeviceInfo</c> function to obtain additional information about a source or target for an adapter, such
/// as the display name, the preferred display mode, and source device name.
/// </para>
/// <para>
/// The caller can call <c>DisplayConfigGetDeviceInfo</c> to obtain more friendly names to display in the user interface. The caller
/// can obtain names for the adapter, the source, and the target. The caller can also call <c>DisplayConfigGetDeviceInfo</c> to
/// obtain the best resolution of the connected display device.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-displayconfiggetdeviceinfo LONG
// DisplayConfigGetDeviceInfo( DISPLAYCONFIG_DEVICE_INFO_HEADER *requestPacket );
[DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winuser.h", MSDNShortId = "249dcb1a-4ce3-4478-8331-fb81e91313b0")]
public static extern Win32Error DisplayConfigGetDeviceInfo(IntPtr requestPacket);
/// <summary>The <c>DisplayConfigGetDeviceInfo</c> function retrieves display configuration information about the device.</summary>
/// <typeparam name="T">The type of structure to return. This must match the type supported by <paramref name="type"/>.</typeparam>
/// <param name="adapterId">
/// A locally unique identifier (LUID) that identifies the adapter that the device information packet refers to.
/// </param>
/// <param name="id">
/// The source or target identifier to get or set the device information for. The meaning of this identifier is related to the type
/// of information being requested. For example, in the case of DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME, this is the source identifier.
/// </param>
/// <param name="type">
/// A DISPLAYCONFIG_DEVICE_INFO_TYPE enumerated value that determines the type of device information to retrieve or set. The
/// remainder of the packet for the retrieve or set operation follows immediately after the DISPLAYCONFIG_DEVICE_INFO_HEADER
/// structure. Leave this value as the default (0) to have the value inferred from <typeparamref name="T"/>.
/// </param>
/// <returns>The value of type <typeparamref name="T"/> for the information provided.</returns>
/// <exception cref="ArgumentException">Request type does not match type param value.</exception>
public static T DisplayConfigGetDeviceInfo<T>(ulong adapterId, uint id, DISPLAYCONFIG_DEVICE_INFO_TYPE type = 0) where T : struct
{
if (type == 0)
{
if (!CorrespondingTypeAttribute.CanGet<T, DISPLAYCONFIG_DEVICE_INFO_TYPE>(out type)) throw new ArgumentException("Unable to find enum value matching supplied type param.");
}
else if (!CorrespondingTypeAttribute.CanGet(type, typeof(T))) throw new ArgumentException("Request type does not match type param value.");
var hdr = new DISPLAYCONFIG_DEVICE_INFO_HEADER { size = (uint)Marshal.SizeOf(typeof(T)), type = type, adapterId = adapterId, id = id };
var mem = new SafeHGlobalHandle((int)hdr.size);
mem.Zero();
Marshal.StructureToPtr(hdr, (IntPtr)mem, false);
var hdr2 = mem.ToStructure<T>();
var err = DisplayConfigGetDeviceInfo((IntPtr)mem);
err.ThrowIfFailed();
return mem.ToStructure<T>();
}
/// <summary>The <c>DisplayConfigSetDeviceInfo</c> function sets the properties of a target.</summary>
/// <param name="setPacket">
/// A pointer to a DISPLAYCONFIG_DEVICE_INFO_HEADER structure that contains information to set for the device. The type and size of
/// additional data that <c>DisplayConfigSetDeviceInfo</c> uses for the configuration comes after the header structure. This
/// additional data depends on the packet type, as specified by the <c>type</c> member of DISPLAYCONFIG_DEVICE_INFO_HEADER. For
/// example, if the caller wants to change the boot persistence, that caller allocates and fills a
/// DISPLAYCONFIG_SET_TARGET_PERSISTENCE structure and passes a pointer to this structure in setPacket. Note that the first member of
/// the DISPLAYCONFIG_SET_TARGET_PERSISTENCE structure is the DISPLAYCONFIG_DEVICE_INFO_HEADER.
/// </param>
/// <returns>
/// <para>The function returns one of the following return codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function succeeded.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>The combination of parameters and flags specified are invalid.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_SUPPORTED</term>
/// <term>
/// The system is not running a graphics driver that was written according to the Windows Display Driver Model (WDDM). The function
/// is only supported on a system with a WDDM driver running.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The caller does not have access to the console session. This error occurs if the calling process does not have access to the
/// current desktop or is running on a remote session.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_INSUFFICIENT_BUFFER</term>
/// <term>The size of the packet that the caller passes is not big enough.</term>
/// </item>
/// <item>
/// <term>ERROR_GEN_FAILURE</term>
/// <term>An unspecified error occurred.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// <c>DisplayConfigSetDeviceInfo</c> can currently only be used to start and stop boot persisted force projection on an analog
/// target. For more information about boot persistence, see Forced Versus Connected Targets.
/// </para>
/// <para>
/// <c>DisplayConfigSetDeviceInfo</c> can only be used to set DISPLAYCONFIG_DEVICE_INFO_SET_XXX type of information.
/// <c>DisplayConfigSetDeviceInfo</c> fails if the <c>type</c> member of DISPLAYCONFIG_DEVICE_INFO_HEADER is set to one of the
/// DISPLAYCONFIG_DEVICE_INFO_GET_XXX values.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-displayconfigsetdeviceinfo LONG
// DisplayConfigSetDeviceInfo( DISPLAYCONFIG_DEVICE_INFO_HEADER *setPacket );
[DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winuser.h", MSDNShortId = "4050b1f0-a588-427c-a0df-eefdc488fc20")]
public static extern Win32Error DisplayConfigSetDeviceInfo(IntPtr setPacket);
/// <summary>The <c>DisplayConfigSetDeviceInfo</c> function sets the properties of a target.</summary>
/// <typeparam name="T">The type of the value to set.</typeparam>
/// <param name="value">Contains information to set for the device.</param>
/// <exception cref="ArgumentException">Supplied type does not match valid set value.</exception>
public static void DisplayConfigSetDeviceInfo<T>(T value) where T : struct
{
if (!CorrespondingTypeAttribute.CanSet(typeof(DISPLAYCONFIG_DEVICE_INFO_TYPE), typeof(T))) throw new ArgumentException("Supplied type does not match valid set value.");
var mem = SafeHGlobalHandle.CreateFromStructure(value);
DisplayConfigSetDeviceInfo((IntPtr)mem).ThrowIfFailed();
}
/// <summary>
/// The <c>GetDisplayConfigBufferSizes</c> function retrieves the size of the buffers that are required to call the
/// QueryDisplayConfig function.
/// </summary>
/// <param name="flags">
/// <para>The type of information to retrieve. The value for the Flags parameter must be one of the following values.</para>
/// <para>QDC_ALL_PATHS</para>
/// <para>The caller requests the table sizes to hold all the possible path combinations.</para>
/// <para>QDC_ONLY_ACTIVE_PATHS</para>
/// <para>The caller requests the table sizes to hold only active paths.</para>
/// <para>QDC_DATABASE_CURRENT</para>
/// <para>
/// The caller requests the table sizes to hold the active paths as defined in the persistence database for the currently connected monitors.
/// </para>
/// </param>
/// <param name="numPathArrayElements">
/// Pointer to a variable that receives the number of elements in the path information table. The pNumPathArrayElements parameter
/// value is then used by a subsequent call to the QueryDisplayConfig function. This parameter cannot be <c>NULL</c>.
/// </param>
/// <param name="numModeInfoArrayElements">
/// Pointer to a variable that receives the number of elements in the mode information table. The pNumModeInfoArrayElements parameter
/// value is then used by a subsequent call to the QueryDisplayConfig function. This parameter cannot be <c>NULL</c>.
/// </param>
/// <returns>
/// <para>The function returns one of the following return codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function succeeded.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>The combination of parameters and flags that are specified is invalid.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_SUPPORTED</term>
/// <term>
/// The system is not running a graphics driver that was written according to the Windows Display Driver Model (WDDM). The function
/// is only supported on a system with a WDDM driver running.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The caller does not have access to the console session. This error occurs if the calling process does not have access to the
/// current desktop or is running on a remote session.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_GEN_FAILURE</term>
/// <term>An unspecified error occurred.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Given the current display path configuration and the requested flags, <c>GetDisplayConfigBufferSizes</c> returns the size of the
/// path and mode tables that are required to store the information. <c>GetDisplayConfigBufferSizes</c> can return values that are
/// slightly larger than are actually required because it determines that all source and target paths are valid; whereas, the driver
/// might place some restrictions on the possible combinations.
/// </para>
/// <para>
/// As <c>GetDisplayConfigBufferSizes</c> can only determine the required array size of that moment in time, it is possible that
/// between calls to <c>GetDisplayConfigBufferSizes</c> and QueryDisplayConfig the system configuration has changed and the provided
/// array sizes are no longer sufficient to store the new path data.
/// </para>
/// <para>
/// If a caller is aware that it must enable additional sources and targets, the caller can allocate a larger mode information array
/// than is returned from <c>GetDisplayConfigBufferSizes</c> so that it has the space to add the additional source and target modes
/// after calling <c>QueryDisplayConfig</c> and before calling SetDisplayConfig.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getdisplayconfigbuffersizes LONG
// GetDisplayConfigBufferSizes( UINT32 flags, UINT32 *numPathArrayElements, UINT32 *numModeInfoArrayElements );
[DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winuser.h", MSDNShortId = "5ec7f521-28b5-4922-a3fc-aa4433de69e0")]
public static extern Win32Error GetDisplayConfigBufferSizes(QDC flags, out uint numPathArrayElements, out uint numModeInfoArrayElements);
/// <summary>
/// The <c>QueryDisplayConfig</c> function retrieves information about all possible display paths for all display devices, or views,
/// in the current setting.
/// </summary>
/// <param name="flags">
/// <para>The type of information to retrieve. The value for the Flags parameter must be one of the following values.</para>
/// <para>QDC_ALL_PATHS</para>
/// <para>All the possible path combinations of sources to targets.</para>
/// <para>
/// <c>Note</c> In the case of any temporary modes, the QDC_ALL_PATHS setting means the mode data returned may not be the same as
/// that which is stored in the persistence database.
/// </para>
/// <para>QDC_ONLY_ACTIVE_PATHS</para>
/// <para>Currently active paths only.</para>
/// <para>
/// <c>Note</c> In the case of any temporary modes, the QDC_ONLY_ACTIVE_PATHS setting means the mode data returned may not be the
/// same as that which is stored in the persistence database.
/// </para>
/// <para>QDC_DATABASE_CURRENT</para>
/// <para>Active path as defined in the CCD database for the currently connected displays.</para>
/// </param>
/// <param name="numPathArrayElements">
/// Pointer to a variable that contains the number of elements in pPathInfoArray. This parameter cannot be <c>NULL</c>. If
/// <c>QueryDisplayConfig</c> returns ERROR_SUCCESS, pNumPathInfoElements is updated with the number of valid entries in pPathInfoArray.
/// </param>
/// <param name="pathArray">
/// Pointer to a variable that contains an array of DISPLAYCONFIG_PATH_INFO elements. Each element in pPathInfoArray describes a
/// single path from a source to a target. The source and target mode information indexes are only valid in combination with the
/// pmodeInfoArray tables that are returned for the API at the same time. This parameter cannot be <c>NULL</c>. The pPathInfoArray is
/// always returned in path priority order. For more information about path priority order, see Path Priority Order.
/// </param>
/// <param name="numModeInfoArrayElements">
/// Pointer to a variable that specifies the number in element of the mode information table. This parameter cannot be <c>NULL</c>.
/// If <c>QueryDisplayConfig</c> returns ERROR_SUCCESS, pNumModeInfoArrayElements is updated with the number of valid entries in pModeInfoArray.
/// </param>
/// <param name="modeInfoArray">
/// Pointer to a variable that contains an array of DISPLAYCONFIG_MODE_INFO elements. This parameter cannot be <c>NULL</c>.
/// </param>
/// <param name="currentTopologyId">
/// <para>
/// Pointer to a variable that receives the identifier of the currently active topology in the CCD database. For a list of possible
/// values, see the DISPLAYCONFIG_TOPOLOGY_ID enumerated type.
/// </para>
/// <para>The pCurrentTopologyId parameter is only set when the Flags parameter value is QDC_DATABASE_CURRENT.</para>
/// <para>
/// If the Flags parameter value is set to QDC_DATABASE_CURRENT, the pCurrentTopologyId parameter must not be <c>NULL</c>. If the
/// Flags parameter value is not set to QDC_DATABASE_CURRENT, the pCurrentTopologyId parameter value must be <c>NULL</c>.
/// </para>
/// </param>
/// <returns>
/// <para>The function returns one of the following return codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function succeeded.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>The combination of parameters and flags that are specified is invalid.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_SUPPORTED</term>
/// <term>
/// The system is not running a graphics driver that was written according to the Windows Display Driver Model (WDDM). The function
/// is only supported on a system with a WDDM driver running.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The caller does not have access to the console session. This error occurs if the calling process does not have access to the
/// current desktop or is running on a remote session.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_GEN_FAILURE</term>
/// <term>An unspecified error occurred.</term>
/// </item>
/// <item>
/// <term>ERROR_INSUFFICIENT_BUFFER</term>
/// <term>The supplied path and mode buffer are too small.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// As the GetDisplayConfigBufferSizes function can only determine the required array size at a particular moment in time, it is
/// possible that between calls to <c>GetDisplayConfigBufferSizes</c> and <c>QueryDisplayConfig</c> the system configuration will
/// change and the provided array sizes will no longer be sufficient to store the new path data. In this situation,
/// <c>QueryDisplayConfig</c> fails with ERROR_INSUFFICIENT_BUFFER, and the caller should call <c>GetDisplayConfigBufferSizes</c>
/// again to get the new array sizes. The caller should then allocate the correct amount of memory.
/// </para>
/// <para>
/// <c>QueryDisplayConfig</c> returns paths in the path array that the pPathInfoArray parameter specifies and the source and target
/// modes in the mode array that the pModeInfoArray parameter specifies. <c>QueryDisplayConfig</c> always returns paths in path
/// priority order. If QDC_ALL_PATHS is set in the Flags parameter, <c>QueryDisplayConfig</c> returns all the inactive paths after
/// the active paths.
/// </para>
/// <para>
/// Full path, source mode, and target mode information is available for all active paths. The <c>ModeInfoIdx</c> members in the
/// DISPLAYCONFIG_PATH_SOURCE_INFO and DISPLAYCONFIG_PATH_TARGET_INFO structures for the source and target are set up for these
/// active paths. For inactive paths, returned source and target mode information is not available; therefore, the target information
/// in the path structure is set to default values, and the source and target mode indexes are marked as invalid. For database
/// queries, if the current connect monitors have an entry, <c>QueryDisplayConfig</c> returns full path, source mode, and target mode
/// information (same as for active paths). However, if the database does not have a entry, <c>QueryDisplayConfig</c> returns just
/// the path information with the default target details (same as for inactive paths).
/// </para>
/// <para>
/// For an example of how source and target mode information relates to path information, see Relationship of Mode Information to
/// Path Information.
/// </para>
/// <para>
/// The caller can use DisplayConfigGetDeviceInfo to obtain additional information about the source or target device, for example,
/// the monitor names and monitor preferred mode and source device name.
/// </para>
/// <para>
/// If a target is currently being force projected, the <c>statusFlags</c> member of the DISPLAYCONFIG_PATH_TARGET_INFO structure has
/// one of the DISPLAYCONFIG_TARGET_FORCED_XXX flags set.
/// </para>
/// <para>
/// If the QDC_DATABASE_CURRENT flag is set in the Flags parameter, <c>QueryDisplayConfig</c> returns the topology identifier of the
/// active database topology in the variable that the pCurrentTopologyId parameter points to. If the QDC_ALL_PATHS or
/// QDC_ONLY_ACTIVE_PATHS flag is set in the Flags parameter, the pCurrentTopologyId parameter must be set to <c>NULL</c>; otherwise,
/// <c>QueryDisplayConfig</c> returns ERROR_INVALID_PARAMETER.
/// </para>
/// <para>
/// If a caller calls <c>QueryDisplayConfig</c> with the QDC_DATABASE_CURRENT flag set in the Flags parameter,
/// <c>QueryDisplayConfig</c> initializes the DISPLAYCONFIG_2DREGION structure that is specified in the <c>totalSize</c> member of
/// the DISPLAYCONFIG_VIDEO_SIGNAL_INFO structure to zeros and does not complete DISPLAYCONFIG_2DREGION.
/// </para>
/// <para>
/// The DEVMODE structure that is returned by the EnumDisplaySettings Win32 function (described in the Windows SDK documentation)
/// contains information that relates to both the source and target modes. However, the CCD APIs explicitly separate the source and
/// target mode components.
/// </para>
/// <para>DPI Virtualization</para>
/// <para>
/// This API does not participate in DPI virtualization. All sizes in the DEVMODE structure are in terms of physical pixels, and are
/// not related to the calling context.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-querydisplayconfig LONG QueryDisplayConfig( UINT32 flags,
// UINT32 *numPathArrayElements, DISPLAYCONFIG_PATH_INFO *pathArray, UINT32 *numModeInfoArrayElements, DISPLAYCONFIG_MODE_INFO
// *modeInfoArray, DISPLAYCONFIG_TOPOLOGY_ID *currentTopologyId );
[DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winuser.h", MSDNShortId = "b1792d7f-f216-4250-a6b6-a11b251a9cec")]
public static extern Win32Error QueryDisplayConfig(QDC flags, ref uint numPathArrayElements, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] DISPLAYCONFIG_PATH_INFO[] pathArray,
ref uint numModeInfoArrayElements, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] DISPLAYCONFIG_MODE_INFO[] modeInfoArray, IntPtr currentTopologyId = default);
/// <summary>
/// The <c>QueryDisplayConfig</c> function retrieves information about all possible display paths for all display devices, or views,
/// in the current setting.
/// </summary>
/// <param name="flags">
/// <para>The type of information to retrieve. The value for the Flags parameter must be one of the following values.</para>
/// <para>QDC_ALL_PATHS</para>
/// <para>All the possible path combinations of sources to targets.</para>
/// <para>
/// <c>Note</c> In the case of any temporary modes, the QDC_ALL_PATHS setting means the mode data returned may not be the same as
/// that which is stored in the persistence database.
/// </para>
/// <para>QDC_ONLY_ACTIVE_PATHS</para>
/// <para>Currently active paths only.</para>
/// <para>
/// <c>Note</c> In the case of any temporary modes, the QDC_ONLY_ACTIVE_PATHS setting means the mode data returned may not be the
/// same as that which is stored in the persistence database.
/// </para>
/// <para>QDC_DATABASE_CURRENT</para>
/// <para>Active path as defined in the CCD database for the currently connected displays.</para>
/// </param>
/// <param name="numPathArrayElements">
/// Pointer to a variable that contains the number of elements in pPathInfoArray. This parameter cannot be <c>NULL</c>. If
/// <c>QueryDisplayConfig</c> returns ERROR_SUCCESS, pNumPathInfoElements is updated with the number of valid entries in pPathInfoArray.
/// </param>
/// <param name="pathArray">
/// Pointer to a variable that contains an array of DISPLAYCONFIG_PATH_INFO elements. Each element in pPathInfoArray describes a
/// single path from a source to a target. The source and target mode information indexes are only valid in combination with the
/// pmodeInfoArray tables that are returned for the API at the same time. This parameter cannot be <c>NULL</c>. The pPathInfoArray is
/// always returned in path priority order. For more information about path priority order, see Path Priority Order.
/// </param>
/// <param name="numModeInfoArrayElements">
/// Pointer to a variable that specifies the number in element of the mode information table. This parameter cannot be <c>NULL</c>.
/// If <c>QueryDisplayConfig</c> returns ERROR_SUCCESS, pNumModeInfoArrayElements is updated with the number of valid entries in pModeInfoArray.
/// </param>
/// <param name="modeInfoArray">
/// Pointer to a variable that contains an array of DISPLAYCONFIG_MODE_INFO elements. This parameter cannot be <c>NULL</c>.
/// </param>
/// <param name="currentTopologyId">
/// <para>
/// Pointer to a variable that receives the identifier of the currently active topology in the CCD database. For a list of possible
/// values, see the DISPLAYCONFIG_TOPOLOGY_ID enumerated type.
/// </para>
/// <para>The pCurrentTopologyId parameter is only set when the Flags parameter value is QDC_DATABASE_CURRENT.</para>
/// <para>
/// If the Flags parameter value is set to QDC_DATABASE_CURRENT, the pCurrentTopologyId parameter must not be <c>NULL</c>. If the
/// Flags parameter value is not set to QDC_DATABASE_CURRENT, the pCurrentTopologyId parameter value must be <c>NULL</c>.
/// </para>
/// </param>
/// <returns>
/// <para>The function returns one of the following return codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function succeeded.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>The combination of parameters and flags that are specified is invalid.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_SUPPORTED</term>
/// <term>
/// The system is not running a graphics driver that was written according to the Windows Display Driver Model (WDDM). The function
/// is only supported on a system with a WDDM driver running.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The caller does not have access to the console session. This error occurs if the calling process does not have access to the
/// current desktop or is running on a remote session.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_GEN_FAILURE</term>
/// <term>An unspecified error occurred.</term>
/// </item>
/// <item>
/// <term>ERROR_INSUFFICIENT_BUFFER</term>
/// <term>The supplied path and mode buffer are too small.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// As the GetDisplayConfigBufferSizes function can only determine the required array size at a particular moment in time, it is
/// possible that between calls to <c>GetDisplayConfigBufferSizes</c> and <c>QueryDisplayConfig</c> the system configuration will
/// change and the provided array sizes will no longer be sufficient to store the new path data. In this situation,
/// <c>QueryDisplayConfig</c> fails with ERROR_INSUFFICIENT_BUFFER, and the caller should call <c>GetDisplayConfigBufferSizes</c>
/// again to get the new array sizes. The caller should then allocate the correct amount of memory.
/// </para>
/// <para>
/// <c>QueryDisplayConfig</c> returns paths in the path array that the pPathInfoArray parameter specifies and the source and target
/// modes in the mode array that the pModeInfoArray parameter specifies. <c>QueryDisplayConfig</c> always returns paths in path
/// priority order. If QDC_ALL_PATHS is set in the Flags parameter, <c>QueryDisplayConfig</c> returns all the inactive paths after
/// the active paths.
/// </para>
/// <para>
/// Full path, source mode, and target mode information is available for all active paths. The <c>ModeInfoIdx</c> members in the
/// DISPLAYCONFIG_PATH_SOURCE_INFO and DISPLAYCONFIG_PATH_TARGET_INFO structures for the source and target are set up for these
/// active paths. For inactive paths, returned source and target mode information is not available; therefore, the target information
/// in the path structure is set to default values, and the source and target mode indexes are marked as invalid. For database
/// queries, if the current connect monitors have an entry, <c>QueryDisplayConfig</c> returns full path, source mode, and target mode
/// information (same as for active paths). However, if the database does not have a entry, <c>QueryDisplayConfig</c> returns just
/// the path information with the default target details (same as for inactive paths).
/// </para>
/// <para>
/// For an example of how source and target mode information relates to path information, see Relationship of Mode Information to
/// Path Information.
/// </para>
/// <para>
/// The caller can use DisplayConfigGetDeviceInfo to obtain additional information about the source or target device, for example,
/// the monitor names and monitor preferred mode and source device name.
/// </para>
/// <para>
/// If a target is currently being force projected, the <c>statusFlags</c> member of the DISPLAYCONFIG_PATH_TARGET_INFO structure has
/// one of the DISPLAYCONFIG_TARGET_FORCED_XXX flags set.
/// </para>
/// <para>
/// If the QDC_DATABASE_CURRENT flag is set in the Flags parameter, <c>QueryDisplayConfig</c> returns the topology identifier of the
/// active database topology in the variable that the pCurrentTopologyId parameter points to. If the QDC_ALL_PATHS or
/// QDC_ONLY_ACTIVE_PATHS flag is set in the Flags parameter, the pCurrentTopologyId parameter must be set to <c>NULL</c>; otherwise,
/// <c>QueryDisplayConfig</c> returns ERROR_INVALID_PARAMETER.
/// </para>
/// <para>
/// If a caller calls <c>QueryDisplayConfig</c> with the QDC_DATABASE_CURRENT flag set in the Flags parameter,
/// <c>QueryDisplayConfig</c> initializes the DISPLAYCONFIG_2DREGION structure that is specified in the <c>totalSize</c> member of
/// the DISPLAYCONFIG_VIDEO_SIGNAL_INFO structure to zeros and does not complete DISPLAYCONFIG_2DREGION.
/// </para>
/// <para>
/// The DEVMODE structure that is returned by the EnumDisplaySettings Win32 function (described in the Windows SDK documentation)
/// contains information that relates to both the source and target modes. However, the CCD APIs explicitly separate the source and
/// target mode components.
/// </para>
/// <para>DPI Virtualization</para>
/// <para>
/// This API does not participate in DPI virtualization. All sizes in the DEVMODE structure are in terms of physical pixels, and are
/// not related to the calling context.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-querydisplayconfig LONG QueryDisplayConfig( UINT32 flags,
// UINT32 *numPathArrayElements, DISPLAYCONFIG_PATH_INFO *pathArray, UINT32 *numModeInfoArrayElements, DISPLAYCONFIG_MODE_INFO
// *modeInfoArray, DISPLAYCONFIG_TOPOLOGY_ID *currentTopologyId );
[DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winuser.h", MSDNShortId = "b1792d7f-f216-4250-a6b6-a11b251a9cec")]
public static extern Win32Error QueryDisplayConfig(QDC flags, ref uint numPathArrayElements, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] DISPLAYCONFIG_PATH_INFO[] pathArray,
ref uint numModeInfoArrayElements, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] DISPLAYCONFIG_MODE_INFO[] modeInfoArray, out DISPLAYCONFIG_TOPOLOGY_ID currentTopologyId);
/// <summary>
/// The <c>QueryDisplayConfig</c> function retrieves information about all possible display paths for all display devices, or views,
/// in the current setting. This method also calls GetDisplayConfigBufferSizes to determine output sizing.
/// </summary>
/// <param name="flags">
/// <para>The type of information to retrieve. The value for the Flags parameter must be one of the following values.</para>
/// <para>QDC_ALL_PATHS</para>
/// <para>All the possible path combinations of sources to targets.</para>
/// <para>
/// <c>Note</c> In the case of any temporary modes, the QDC_ALL_PATHS setting means the mode data returned may not be the same as
/// that which is stored in the persistence database.
/// </para>
/// <para>QDC_ONLY_ACTIVE_PATHS</para>
/// <para>Currently active paths only.</para>
/// <para>
/// <c>Note</c> In the case of any temporary modes, the QDC_ONLY_ACTIVE_PATHS setting means the mode data returned may not be the
/// same as that which is stored in the persistence database.
/// </para>
/// <para>QDC_DATABASE_CURRENT</para>
/// <para>Active path as defined in the CCD database for the currently connected displays.</para>
/// </param>
/// <param name="pathArray">
/// The resulting array of DISPLAYCONFIG_PATH_INFO elements. Each element in pPathInfoArray describes a single path from a source to
/// a target. The source and target mode information indexes are only valid in combination with the pmodeInfoArray tables that are
/// returned for the API at the same time. This parameter cannot be <c>NULL</c>. The pPathInfoArray is always returned in path
/// priority order. For more information about path priority order, see Path Priority Order.
/// </param>
/// <param name="modeInfoArray">The resulting array of DISPLAYCONFIG_MODE_INFO elements.</param>
/// <param name="currentTopologyId">
/// <para>
/// Pointer to a variable that receives the identifier of the currently active topology in the CCD database. For a list of possible
/// values, see the DISPLAYCONFIG_TOPOLOGY_ID enumerated type.
/// </para>
/// <para>The pCurrentTopologyId parameter is only set when the Flags parameter value is QDC_DATABASE_CURRENT.</para>
/// <para>
/// If the Flags parameter value is set to QDC_DATABASE_CURRENT, the pCurrentTopologyId parameter must not be <c>NULL</c>. If the
/// Flags parameter value is not set to QDC_DATABASE_CURRENT, the pCurrentTopologyId parameter value must be <c>NULL</c>.
/// </para>
/// </param>
/// <returns>
/// <para>The function returns one of the following return codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function succeeded.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>The combination of parameters and flags that are specified is invalid.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_SUPPORTED</term>
/// <term>
/// The system is not running a graphics driver that was written according to the Windows Display Driver Model (WDDM). The function
/// is only supported on a system with a WDDM driver running.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The caller does not have access to the console session. This error occurs if the calling process does not have access to the
/// current desktop or is running on a remote session.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_GEN_FAILURE</term>
/// <term>An unspecified error occurred.</term>
/// </item>
/// <item>
/// <term>ERROR_INSUFFICIENT_BUFFER</term>
/// <term>The supplied path and mode buffer are too small.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// <c>QueryDisplayConfig</c> returns paths in the path array that the pPathInfoArray parameter specifies and the source and target
/// modes in the mode array that the pModeInfoArray parameter specifies. <c>QueryDisplayConfig</c> always returns paths in path
/// priority order. If QDC_ALL_PATHS is set in the Flags parameter, <c>QueryDisplayConfig</c> returns all the inactive paths after
/// the active paths.
/// </para>
/// <para>
/// Full path, source mode, and target mode information is available for all active paths. The <c>ModeInfoIdx</c> members in the
/// DISPLAYCONFIG_PATH_SOURCE_INFO and DISPLAYCONFIG_PATH_TARGET_INFO structures for the source and target are set up for these
/// active paths. For inactive paths, returned source and target mode information is not available; therefore, the target information
/// in the path structure is set to default values, and the source and target mode indexes are marked as invalid. For database
/// queries, if the current connect monitors have an entry, <c>QueryDisplayConfig</c> returns full path, source mode, and target mode
/// information (same as for active paths). However, if the database does not have a entry, <c>QueryDisplayConfig</c> returns just
/// the path information with the default target details (same as for inactive paths).
/// </para>
/// <para>
/// For an example of how source and target mode information relates to path information, see Relationship of Mode Information to
/// Path Information.
/// </para>
/// <para>
/// The caller can use DisplayConfigGetDeviceInfo to obtain additional information about the source or target device, for example,
/// the monitor names and monitor preferred mode and source device name.
/// </para>
/// <para>
/// If a target is currently being force projected, the <c>statusFlags</c> member of the DISPLAYCONFIG_PATH_TARGET_INFO structure has
/// one of the DISPLAYCONFIG_TARGET_FORCED_XXX flags set.
/// </para>
/// <para>
/// If the QDC_DATABASE_CURRENT flag is set in the Flags parameter, <c>QueryDisplayConfig</c> returns the topology identifier of the
/// active database topology in the variable that the pCurrentTopologyId parameter points to. If the QDC_ALL_PATHS or
/// QDC_ONLY_ACTIVE_PATHS flag is set in the Flags parameter, the pCurrentTopologyId parameter must be set to <c>NULL</c>; otherwise,
/// <c>QueryDisplayConfig</c> returns ERROR_INVALID_PARAMETER.
/// </para>
/// <para>
/// If a caller calls <c>QueryDisplayConfig</c> with the QDC_DATABASE_CURRENT flag set in the Flags parameter,
/// <c>QueryDisplayConfig</c> initializes the DISPLAYCONFIG_2DREGION structure that is specified in the <c>totalSize</c> member of
/// the DISPLAYCONFIG_VIDEO_SIGNAL_INFO structure to zeros and does not complete DISPLAYCONFIG_2DREGION.
/// </para>
/// <para>
/// The DEVMODE structure that is returned by the EnumDisplaySettings Win32 function (described in the Windows SDK documentation)
/// contains information that relates to both the source and target modes. However, the CCD APIs explicitly separate the source and
/// target mode components.
/// </para>
/// <para>DPI Virtualization</para>
/// <para>
/// This API does not participate in DPI virtualization. All sizes in the DEVMODE structure are in terms of physical pixels, and are
/// not related to the calling context.
/// </para>
/// </remarks>
[PInvokeData("winuser.h", MSDNShortId = "b1792d7f-f216-4250-a6b6-a11b251a9cec")]
public static Win32Error QueryDisplayConfig(QDC flags, out DISPLAYCONFIG_PATH_INFO[] pathArray, out DISPLAYCONFIG_MODE_INFO[] modeInfoArray, out DISPLAYCONFIG_TOPOLOGY_ID currentTopologyId)
{
Win32Error err;
do
{
err = GetDisplayConfigBufferSizes(flags, out var cPath, out var cMode);
pathArray = new DISPLAYCONFIG_PATH_INFO[err.Failed ? 0 : cPath];
modeInfoArray = new DISPLAYCONFIG_MODE_INFO[err.Failed ? 0 : cMode];
currentTopologyId = 0;
if (err.Failed) return err;
if (flags.IsFlagSet(QDC.QDC_DATABASE_CURRENT))
err = QueryDisplayConfig(flags, ref cPath, pathArray, ref cMode, modeInfoArray, out currentTopologyId);
else
err = QueryDisplayConfig(flags, ref cPath, pathArray, ref cMode, modeInfoArray);
if (err.Succeeded || err != Win32Error.ERROR_INSUFFICIENT_BUFFER) return err;
} while (err == Win32Error.ERROR_INSUFFICIENT_BUFFER);
return err;
}
/// <summary>
/// The <c>SetDisplayConfig</c> function modifies the display topology, source, and target modes by exclusively enabling the
/// specified paths in the current session.
/// </summary>
/// <param name="numPathArrayElements">Number of elements in pathArray.</param>
/// <param name="pathArray">
/// Array of all display paths that are to be set. Only the paths within this array that have the DISPLAYCONFIG_PATH_ACTIVE flag set
/// in the <c>flags</c> member of DISPLAYCONFIG_PATH_INFO are set. This parameter can be <c>NULL</c>. The order in which active paths
/// appear in this array determines the path priority. For more information about path priority order, see Path Priority Order.
/// </param>
/// <param name="numModeInfoArrayElements">Number of elements in modeInfoArray.</param>
/// <param name="modeInfoArray">
/// Array of display source and target mode information (DISPLAYCONFIG_MODE_INFO) that is referenced by the <c>modeInfoIdx</c> member
/// of DISPLAYCONFIG_PATH_SOURCE_INFO and DISPLAYCONFIG_PATH_TARGET_INFO element of path information from pathArray. This parameter
/// can be <c>NULL</c>.
/// </param>
/// <param name="flags">
/// <para>
/// A bitwise OR of flag values that indicates the behavior of this function. This parameter can be one the following values, or a
/// combination of the following values; 0 is not valid.
/// </para>
/// <para>SDC_APPLY</para>
/// <para>The resulting topology, source, and target mode is set.</para>
/// <para>SDC_NO_OPTIMIZATION</para>
/// <para>
/// A modifier to the SDC_APPLY flag. This causes the change mode to be forced all the way down to the driver for each active display.
/// </para>
/// <para>SDC_USE_SUPPLIED_DISPLAY_CONFIG</para>
/// <para>
/// The topology, source, and target mode information that are supplied in the pathArray and the modeInfoArray parameters are used,
/// rather than looking up the configuration in the database.
/// </para>
/// <para>SDC_SAVE_TO_DATABASE</para>
/// <para>The resulting topology, source, and target mode are saved to the database.</para>
/// <para>SDC_VALIDATE</para>
/// <para>The system tests for the requested topology, source, and target mode information to determine whether it can be set.</para>
/// <para>SDC_ALLOW_CHANGES</para>
/// <para>
/// If required, the function can modify the specified source and target mode information in order to create a functional display
/// path set.
/// </para>
/// <para>SDC_TOPOLOGY_CLONE</para>
/// <para>The caller requests the last clone configuration from the persistence database.</para>
/// <para>SDC_TOPOLOGY_EXTEND</para>
/// <para>The caller requests the last extended configuration from the persistence database.</para>
/// <para>SDC_TOPOLOGY_INTERNAL</para>
/// <para>The caller requests the last internal configuration from the persistence database.</para>
/// <para>SDC_TOPOLOGY_EXTERNAL</para>
/// <para>The caller requests the last external configuration from the persistence database.</para>
/// <para>SDC_TOPOLOGY_SUPPLIED</para>
/// <para>
/// The caller provides the path data so the function only queries the persistence database to find and use the source and target mode.
/// </para>
/// <para>SDC_USE_DATABASE_CURRENT</para>
/// <para>
/// The caller requests a combination of all four SDC_TOPOLOGY_XXX configurations. This value informs the API to set the last known
/// display configuration for the current connected monitors.
/// </para>
/// <para>SDC_PATH_PERSIST_IF_REQUIRED</para>
/// <para>
/// When the function processes a SDC_TOPOLOGY_XXX request, it can force path persistence on a target to satisfy the request if
/// necessary. For information about the other flags that this flag can be combined with, see the following list.
/// </para>
/// <para>SDC_FORCE_MODE_ENUMERATION</para>
/// <para>
/// The caller requests that the driver is given an opportunity to update the GDI mode list while <c>SetDisplayConfig</c> sets the
/// new display configuration. This flag value is only valid when the SDC_USE_SUPPLIED_DISPLAY_CONFIG and SDC_APPLY flag values are
/// also specified.
/// </para>
/// <para>SDC_ALLOW_PATH_ORDER_CHANGES</para>
/// <para>
/// A modifier to the SDC_TOPOLOGY_SUPPLIED flag that indicates that <c>SetDisplayConfig</c> should ignore the path order of the
/// supplied topology when searching the database. When this flag is set, the topology set is the most recent topology that contains
/// all the paths regardless of the path order.
/// </para>
/// <para>The following list contains valid combinations of values for the Flags parameter:</para>
/// <list type="bullet">
/// <item>
/// <term>Either SDC_APPLY or SDC_VALIDATE must be set, but not both.</term>
/// </item>
/// <item>
/// <term>
/// Either SDC_USE_SUPPLIED_DISPLAY_CONFIG or any combinations of SDC_TOPOLOGY_XXX must be set. SDC_USE_SUPPLIED_DISPLAY_CONFIG
/// cannot be set with any SDC_TOPOLOGY_XXX flag.
/// </term>
/// </item>
/// <item>
/// <term>SDC_NO_OPTIMIZATION can only be set with SDC_APPLY.</term>
/// </item>
/// <item>
/// <term>SDC_ALLOW_CHANGES is allowed with any other valid combination.</term>
/// </item>
/// <item>
/// <term>SDC_SAVE_TO_DATABASE can only be set with SDC_USE_SUPPLIED_DISPLAY_CONFIG.</term>
/// </item>
/// <item>
/// <term>SDC_PATH_PERSIST_IF_REQUIRED cannot be used with SDC_USE_SUPPLIED_DISPLAY_CONFIG or SDC_TOPOLOGY_SUPPLIED.</term>
/// </item>
/// <item>
/// <term>SDC_FORCE_MODE_ENUMERATION is only valid when SDC_APPLY and SDC_USE_SUPPLIED_DISPLAY_CONFIG are specified.</term>
/// </item>
/// <item>
/// <term>SDC_ALLOW_PATH_ORDER_CHANGES is allowed only when SDC_TOPOLOGY_SUPPLIED is specified.</term>
/// </item>
/// <item>
/// <term>
/// SDC_TOPOLOGY_SUPPLIED cannot be used with any other SDC_TOPOLOGY_XXX flag. Because of a validation issue, if a caller violates
/// this rule, <c>SetDisplayConfig</c> does not fail. However, <c>SetDisplayConfig</c> ignores the SDC_TOPOLOGY_SUPPLIED flag.
/// </term>
/// </item>
/// </list>
/// <para>
/// SDC_TOPOLOGY_XXX flags can be used in combinations. For example, if SDC_TOPOLOGY_CLONE and SDC_TOPOLOGY_EXTEND are set, the API
/// uses the most recent clone or extend topology, which every topology was set with most recently for the current connected monitors.
/// </para>
/// </param>
/// <returns>
/// <para>The function returns one of the following return codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The function succeeded.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>The combination of parameters and flags specified is invalid.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_SUPPORTED</term>
/// <term>
/// The system is not running a graphics driver that was written according to the Windows Display Driver Model (WDDM). The function
/// is only supported on a system with a WDDM driver running.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The caller does not have access to the console session. This error occurs if the calling process does not have access to the
/// current desktop or is running on a remote session.
/// </term>
/// </item>
/// <item>
/// <term>ERROR_GEN_FAILURE</term>
/// <term>An unspecified error occurred.</term>
/// </item>
/// <item>
/// <term>ERROR_BAD_CONFIGURATION</term>
/// <term>The function could not find a workable solution for the source and target modes that the caller did not specify.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// The <c>SetDisplayConfig</c> function takes the active display paths with any specified source and target mode information and
/// uses best mode logic to generate any missing source and target mode information. This function then sets the complete display path.
/// </para>
/// <para>
/// The <c>ModeInfoIdx</c> members in the DISPLAYCONFIG_PATH_SOURCE_INFO and DISPLAYCONFIG_PATH_TARGET_INFO structures are used to
/// indicate whether source and target mode are supplied for a given active path. If the index value is
/// DISPLAYCONFIG_PATH_MODE_IDX_INVALID for either, this indicates the mode information is not being specified. It is valid for the
/// path plus source mode or the path plus source and target mode information to be specified for a given path. However, it is not
/// valid for the path plus target mode to be specified without the source mode.
/// </para>
/// <para>
/// The source and target modes for each source and target identifiers can only appear in the modeInfoArray array once. For example,
/// a source mode for source identifier S1 can only appear in the table once; if multiple paths reference the same source, they have
/// to use the same <c>ModeInfoIdx</c>.
/// </para>
/// <para>
/// The expectation is that most callers use QueryDisplayConfig to get the current configuration along with other valid possibilities
/// and then use <c>SetDisplayConfig</c> to test and set the configuration.
/// </para>
/// <para>The order in which the active paths appear in the PathArray array determines the path priority.</para>
/// <para>
/// By default, <c>SetDisplayConfig</c> never changes any supplied path, source mode, or target mode information. If best mode logic
/// cannot find a solution without changing the specified display path information, <c>SetDisplayConfig</c> fails with
/// ERROR_BAD_CONFIGURATION. In this case, the caller should specify the SDC_ALLOW_CHANGES flag to allow the function to tweak some
/// of the specified source and mode details to allow the display path change to be successful.
/// </para>
/// <para>
/// If the specified or calculated source and target modes have the same dimensions, <c>SetDisplayConfig</c> automatically sets the
/// path scaling to DISPLAYCONFIG_PPR_IDENTITY before setting the display path and saving it in the database. For information about
/// how <c>SetDisplayConfig</c> handles scaling, see Scaling the Desktop Image.
/// </para>
/// <para>
/// When the caller specifies the SDC_USE_SUPPLIED_DISPLAY_CONFIG flag to set a clone path and if any source mode indexes are invalid
/// in the path array, <c>SetDisplayConfig</c> determines that all of the source mode indexes from that source are invalid.
/// <c>SetDisplayConfig</c> uses the best mode logic to determine the source mode information.
/// </para>
/// <para>
/// Except for the SDC_TOPOLOGY_SUPPLIED flag (for more information about SDC_TOPOLOGY_SUPPLIED, see the following paragraph), the
/// SDC_TOPOLOGY_XXX flags set last display path settings, including the source and target mode information for that topology type.
/// For information about valid SDC_TOPOLOGY_XXX flag combinations, see the Flags parameter description. The pathArray and
/// modeInfoArray parameters must be <c>NULL</c>, and their associated sizes must be zero. For example, if SDC_TOPOLOGY_CLONE and
/// SDC_TOPOLOGY_EXTEND are set, this function uses the most recent clone or extend display path configuration. If a single topology
/// type is requested, the last configuration of that type is used. If that topology had never been set before,
/// <c>SetDisplayConfig</c> uses the best topology logic to find the best topology, and then best mode logic to find the best source
/// and target mode to use. If a combination of the topology flags had been set and none of them had database entries, the following
/// priority is used. For laptops: clone, extend, internal, and then external; for desktops the priority is extend and then clone.
/// </para>
/// <para>
/// The caller can specify the SDC_TOPOLOGY_SUPPLIED flag to indicate that it sets just the path information (topology) and requests
/// that <c>SetDisplayConfig</c> obtains and then uses the source and target mode information from the persistence database. If the
/// active paths that the caller supplies do not have an entry in the persistence database, <c>SetDisplayConfig</c> fails. In this
/// case, if the caller calls <c>SetDisplayConfig</c> again with the same path data but with the SDC_USE_SUPPLIED_DISPLAY_CONFIG flag
/// set, <c>SetDisplayConfig</c> uses best mode logic to create the source and target mode information. When the caller specifies
/// SDC_TOPOLOGY_SUPPLIED, the caller must set the numModeInfoArrayElements parameter to zero and the modeInfoArray parameter to
/// <c>NULL</c>; however, the caller must set the pathArray and numPathArrayElements parameters for the path information that the
/// caller requires. The caller must mark all the source and target mode indexes as invalid (DISPLAYCONFIG_PATH_MODE_IDX_INVALID) in
/// this path data.
/// </para>
/// <para>
/// The following table provides some common scenarios where <c>SetDisplayConfig</c> is called along with the flag combinations that
/// the caller passes to the Flags parameter to achieve the scenarios.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Scenario</term>
/// <term>Flag combination</term>
/// </listheader>
/// <item>
/// <term>Test whether a specified display configuration is supported on the computer</term>
/// <term>SDC_VALIDATE | SDC_USE_SUPPLIED_DISPLAY_CONFIG</term>
/// </item>
/// <item>
/// <term>Set a specified display configuration and save to the database</term>
/// <term>SDC_APPLY | SDC_USE_SUPPLIED_DISPLAY_CONFIG | SDC_SAVE_TO_DATABASE</term>
/// </item>
/// <item>
/// <term>Set a temporary display configuration (that is, the display configuration will not be saved)</term>
/// <term>SDC_APPLY | SDC_USE_SUPPLIED_DISPLAY_CONFIG</term>
/// </item>
/// <item>
/// <term>Test whether clone is supported on the computer</term>
/// <term>SDC_VALIDATE | SDC_TOPOLOGY_CLONE</term>
/// </item>
/// <item>
/// <term>Set clone topology</term>
/// <term>SDC_APPLY | SDC_TOPOLOGY_CLONE</term>
/// </item>
/// <item>
/// <term>Set clone topology and allow path persistence to be enabled if required to satisfy the request</term>
/// <term>SDC_APPLY | SDC_TOPOLOGY_CLONE | SDC_PATH_PERSIST_IF_REQUIRED</term>
/// </item>
/// <item>
/// <term>Return from a temporary mode to the last saved display configuration</term>
/// <term>SDC_APPLY| SDC_USE_DATABASE_CURRENT</term>
/// </item>
/// <item>
/// <term>
/// Given only the path information, set the display configuration with the source and target information from the database for the
/// paths and ignore the path order
/// </term>
/// <term>SDC_APPLY | SDC_TOPOLOGY_SUPPLIED | SDC_ALLOW_PATH_ORDER_CHANGES</term>
/// </item>
/// </list>
/// <para>DPI Virtualization</para>
/// <para>
/// This API does not participate in DPI virtualization. All sizes in the DEVMODE structure are in terms of physical pixels, and are
/// not related to the calling context.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setdisplayconfig LONG SetDisplayConfig( UINT32
// numPathArrayElements, DISPLAYCONFIG_PATH_INFO *pathArray, UINT32 numModeInfoArrayElements, DISPLAYCONFIG_MODE_INFO *modeInfoArray,
// UINT32 flags );
[DllImport(Lib.User32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("winuser.h", MSDNShortId = "9f649fa0-ffb2-44c6-9a66-049f888e3b04")]
public static extern Win32Error SetDisplayConfig(uint numPathArrayElements, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0), Optional] DISPLAYCONFIG_PATH_INFO[] pathArray,
uint numModeInfoArrayElements, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2), Optional] DISPLAYCONFIG_MODE_INFO[] modeInfoArray, SDC flags);
}
}