Have a look:
[DllImport("User32.dll")]
public static extern StatusCode DisplayConfigGetDeviceInfo(
ref IDisplayConfigInfo a
);
and now my structure that inherits from IDisplayConfigInfo:
var displayConfigTargetDeviceName = new DisplayConfigTargetDeviceName
{
header = new DisplayConfigDeviceInfoHeader
{
adapterId = targetModeInfo.adapterId,
id = targetModeInfo.id,
size = Marshal.SizeOf(typeof(DisplayConfigTargetDeviceName)),
type = DisplayConfigDeviceInfoType.GetTargetName,
}
};
var configTargetDeviceName = (IDisplayConfigInfo) displayConfigTargetDeviceName;
var retval = CCDWrapper.DisplayConfigGetDeviceInfo(ref configTargetDeviceName);
Now there is a problem. retval will be returned "InvalidParameter" value. Why is that? It is because I try to use interface, but I don't understand why.
When I explictly say that DisplayConfigGetDeviceInfo() accepts DisplayConfigTargetDeviceName instead of interface, and pass displayconfigTargetDeviceName to it directly, then it works.
The thing is, I don't want to create 8-9 overloads, for each structure. Note that C++ version has only one overload. It will figure out the rest from pointer I passed.
// structs:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct DisplayConfigTargetDeviceName : IDisplayConfigInfo
{
public DisplayConfigDeviceInfoHeader header;
public DisplayConfigTargetDeviceNameFlags flags;
public DisplayConfigVideoOutputTechnology 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;
}
[StructLayout(LayoutKind.Sequential)]
public struct DisplayConfigDeviceInfoHeader
{
public DisplayConfigDeviceInfoType type;
public int size;
public LUID adapterId;
public uint id;
}
and IDisplayConfig interface is empty.
Thanks to David, I was able to come up with clever solution(imo), it seems to work nicely.
[DllImport("User32.dll")]
private static extern StatusCode DisplayConfigSetDeviceInfo(IntPtr requestPacket);
public static StatusCode DisplayConfigSetDeviceInfo<T>(ref T displayConfig)
where T : IDisplayConfigInfo
{
return WrapStructureAndCall(ref displayConfig, DisplayConfigSetDeviceInfo);
}
[DllImport("User32.dll")]
private static extern StatusCode DisplayConfigGetDeviceInfo(IntPtr targetDeviceName);
public static StatusCode DisplayConfigGetDeviceInfo<T>(ref T displayConfig)
where T : IDisplayConfigInfo
{
return WrapStructureAndCall(ref displayConfig, DisplayConfigGetDeviceInfo);
}
public static StatusCode WrapStructureAndCall<T>(ref T displayConfig,
Func<IntPtr, StatusCode> func) where T : IDisplayConfigInfo
{
var ptr = Marshal.AllocHGlobal(Marshal.SizeOf(displayConfig));
Marshal.StructureToPtr(displayConfig, ptr, false);
var retval = func(ptr);
displayConfig = (T)Marshal.PtrToStructure(ptr, displayConfig.GetType());
Marshal.FreeHGlobal(ptr);
return retval;
}