Related
My environment is Windows 10 20H2(64bit) and Visual Studio 2019.
I am developing an app as C# WPF(.NET 5) project. And I want to write a code that HDR(High Dynamic Range) is active currently on the system.
In this document, I got some hints about Windows HDR. But I could only find articles about for UWP and DirectX.
I would ideally like to use the .NET API or Win32 API. Does Windows 10 provide those APIs?
You can use the Connecting and Configuring Displays (CCD) API.
specifically the DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO request (which is not really documented in MSDN but is defined in wingdi.h)
Here is some C# Console Application sample code that dumps for each monitor if it supports HDR and if it's enabled.
static void Main()
{
var err = GetDisplayConfigBufferSizes(QDC.QDC_ONLY_ACTIVE_PATHS, out var pathCount, out var modeCount);
if (err != 0)
throw new Win32Exception(err);
var paths = new DISPLAYCONFIG_PATH_INFO[pathCount];
var modes = new DISPLAYCONFIG_MODE_INFO[modeCount];
err = QueryDisplayConfig(QDC.QDC_ONLY_ACTIVE_PATHS, ref pathCount, paths, ref modeCount, modes, IntPtr.Zero);
if (err != 0)
throw new Win32Exception(err);
foreach (var path in paths)
{
// get display name
var info = new DISPLAYCONFIG_TARGET_DEVICE_NAME();
info.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
info.header.size = Marshal.SizeOf<DISPLAYCONFIG_TARGET_DEVICE_NAME>();
info.header.adapterId = path.targetInfo.adapterId;
info.header.id = path.targetInfo.id;
err = DisplayConfigGetDeviceInfo(ref info);
if (err != 0)
throw new Win32Exception(err);
var colorInfo = new DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO();
colorInfo.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO;
colorInfo.header.size = Marshal.SizeOf<DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO>();
colorInfo.header.adapterId = path.targetInfo.adapterId;
colorInfo.header.id = path.targetInfo.id;
err = DisplayConfigGetDeviceInfo(ref colorInfo);
if (err != 0)
throw new Win32Exception(err);
Console.WriteLine(info.monitorFriendlyDeviceName);
Console.WriteLine(" Advanced Color Supported: " + colorInfo.advancedColorSupported);
Console.WriteLine(" Advanced Color Enabled : " + colorInfo.advancedColorEnabled);
Console.WriteLine();
}
}
private enum DISPLAYCONFIG_DEVICE_INFO_TYPE
{
DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME = 1,
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME = 2,
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE = 3,
DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME = 4,
DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_PERSISTENCE = 5,
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_BASE_TYPE = 6,
DISPLAYCONFIG_DEVICE_INFO_GET_SUPPORT_VIRTUAL_RESOLUTION = 7,
DISPLAYCONFIG_DEVICE_INFO_SET_SUPPORT_VIRTUAL_RESOLUTION = 8,
DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO = 9,
DISPLAYCONFIG_DEVICE_INFO_SET_ADVANCED_COLOR_STATE = 10,
DISPLAYCONFIG_DEVICE_INFO_GET_SDR_WHITE_LEVEL = 11,
}
private enum DISPLAYCONFIG_COLOR_ENCODING
{
DISPLAYCONFIG_COLOR_ENCODING_RGB = 0,
DISPLAYCONFIG_COLOR_ENCODING_YCBCR444 = 1,
DISPLAYCONFIG_COLOR_ENCODING_YCBCR422 = 2,
DISPLAYCONFIG_COLOR_ENCODING_YCBCR420 = 3,
DISPLAYCONFIG_COLOR_ENCODING_INTENSITY = 4,
}
private enum DISPLAYCONFIG_SCALING
{
DISPLAYCONFIG_SCALING_IDENTITY = 1,
DISPLAYCONFIG_SCALING_CENTERED = 2,
DISPLAYCONFIG_SCALING_STRETCHED = 3,
DISPLAYCONFIG_SCALING_ASPECTRATIOCENTEREDMAX = 4,
DISPLAYCONFIG_SCALING_CUSTOM = 5,
DISPLAYCONFIG_SCALING_PREFERRED = 128,
}
private enum DISPLAYCONFIG_ROTATION
{
DISPLAYCONFIG_ROTATION_IDENTITY = 1,
DISPLAYCONFIG_ROTATION_ROTATE90 = 2,
DISPLAYCONFIG_ROTATION_ROTATE180 = 3,
}
private enum DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY
{
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER = -1,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15 = 0,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SVIDEO = 1,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPOSITE_VIDEO = 2,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPONENT_VIDEO = 3,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI = 4,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI = 5,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_LVDS = 6,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_D_JPN = 8,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDI = 9,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL = 10,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED = 11,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EXTERNAL = 12,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED = 13,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDTVDONGLE = 14,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_MIRACAST = 15,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INDIRECT_WIRED = 16,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INDIRECT_VIRTUAL = 17,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL = unchecked((int)0x80000000),
}
private enum DISPLAYCONFIG_TOPOLOGY_ID
{
DISPLAYCONFIG_TOPOLOGY_INTERNAL = 0x00000001,
DISPLAYCONFIG_TOPOLOGY_CLONE = 0x00000002,
DISPLAYCONFIG_TOPOLOGY_EXTEND = 0x00000004,
DISPLAYCONFIG_TOPOLOGY_EXTERNAL = 0x00000008,
}
private enum DISPLAYCONFIG_PATH
{
DISPLAYCONFIG_PATH_ACTIVE = 0x00000001,
DISPLAYCONFIG_PATH_PREFERRED_UNSCALED = 0x00000004,
DISPLAYCONFIG_PATH_SUPPORT_VIRTUAL_MODE = 0x00000008,
}
private enum DISPLAYCONFIG_SOURCE_FLAGS
{
DISPLAYCONFIG_SOURCE_IN_USE = 0x00000001,
}
private enum DISPLAYCONFIG_TARGET_FLAGS
{
DISPLAYCONFIG_TARGET_IN_USE = 0x00000001,
DISPLAYCONFIG_TARGET_FORCIBLE = 0x00000002,
DISPLAYCONFIG_TARGET_FORCED_AVAILABILITY_BOOT = 0x00000004,
DISPLAYCONFIG_TARGET_FORCED_AVAILABILITY_PATH = 0x00000008,
DISPLAYCONFIG_TARGET_FORCED_AVAILABILITY_SYSTEM = 0x00000010,
DISPLAYCONFIG_TARGET_IS_HMD = 0x00000020,
}
private enum QDC
{
QDC_ALL_PATHS = 0x00000001,
QDC_ONLY_ACTIVE_PATHS = 0x00000002,
QDC_DATABASE_CURRENT = 0x00000004,
QDC_VIRTUAL_MODE_AWARE = 0x00000010,
QDC_INCLUDE_HMD = 0x00000020,
}
private enum DISPLAYCONFIG_SCANLINE_ORDERING
{
DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED = 0,
DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE = 1,
DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED = 2,
DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_UPPERFIELDFIRST = DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED,
DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_LOWERFIELDFIRST = 3,
}
private enum DISPLAYCONFIG_PIXELFORMAT
{
DISPLAYCONFIG_PIXELFORMAT_8BPP = 1,
DISPLAYCONFIG_PIXELFORMAT_16BPP = 2,
DISPLAYCONFIG_PIXELFORMAT_24BPP = 3,
DISPLAYCONFIG_PIXELFORMAT_32BPP = 4,
DISPLAYCONFIG_PIXELFORMAT_NONGDI = 5,
}
private enum DISPLAYCONFIG_MODE_INFO_TYPE
{
DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE = 1,
DISPLAYCONFIG_MODE_INFO_TYPE_TARGET = 2,
DISPLAYCONFIG_MODE_INFO_TYPE_DESKTOP_IMAGE = 3,
}
[StructLayout(LayoutKind.Sequential)]
private struct DISPLAYCONFIG_DEVICE_INFO_HEADER
{
public DISPLAYCONFIG_DEVICE_INFO_TYPE type;
public int size;
public LUID adapterId;
public uint id;
}
[StructLayout(LayoutKind.Sequential)]
private struct DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO
{
public DISPLAYCONFIG_DEVICE_INFO_HEADER header;
public uint value;
public DISPLAYCONFIG_COLOR_ENCODING colorEncoding;
public int bitsPerColorChannel;
public bool advancedColorSupported => (value & 0x1) == 0x1;
public bool advancedColorEnabled => (value & 0x2) == 0x2;
public bool wideColorEnforced => (value & 0x4) == 0x4;
public bool advancedColorForceDisabled => (value & 0x8) == 0x8;
}
[StructLayout(LayoutKind.Sequential)]
private struct POINTL
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
private struct LUID
{
public uint LowPart;
public int HighPart;
public long Value => ((long)HighPart << 32) | LowPart;
public override string ToString() => Value.ToString();
}
[StructLayout(LayoutKind.Sequential)]
private struct DISPLAYCONFIG_SOURCE_MODE
{
public uint width;
public uint height;
public DISPLAYCONFIG_PIXELFORMAT pixelFormat;
public POINTL position;
}
[StructLayout(LayoutKind.Sequential)]
private struct DISPLAYCONFIG_RATIONAL
{
public uint Numerator;
public uint Denominator;
public override string ToString() => Numerator + " / " + Denominator;
}
[StructLayout(LayoutKind.Sequential)]
private struct DISPLAYCONFIG_2DREGION
{
public uint cx;
public uint cy;
}
[StructLayout(LayoutKind.Sequential)]
private struct DISPLAYCONFIG_DESKTOP_IMAGE_INFO
{
public POINTL PathSourceSize;
public RECT DesktopImageRegion;
public RECT DesktopImageClip;
}
[StructLayout(LayoutKind.Sequential)]
private struct DISPLAYCONFIG_VIDEO_SIGNAL_INFO
{
public ulong pixelRate;
public DISPLAYCONFIG_RATIONAL hSyncFreq;
public DISPLAYCONFIG_RATIONAL vSyncFreq;
public DISPLAYCONFIG_2DREGION activeSize;
public DISPLAYCONFIG_2DREGION totalSize;
public uint videoStandard;
public DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;
}
[StructLayout(LayoutKind.Sequential)]
private struct DISPLAYCONFIG_TARGET_MODE
{
public DISPLAYCONFIG_VIDEO_SIGNAL_INFO targetVideoSignalInfo;
}
[StructLayout(LayoutKind.Explicit)]
private struct DISPLAYCONFIG_MODE_INFO_union
{
[FieldOffset(0)]
public DISPLAYCONFIG_TARGET_MODE targetMode;
[FieldOffset(0)]
public DISPLAYCONFIG_SOURCE_MODE sourceMode;
[FieldOffset(0)]
public DISPLAYCONFIG_DESKTOP_IMAGE_INFO desktopImageInfo;
}
[StructLayout(LayoutKind.Sequential)]
private struct DISPLAYCONFIG_PATH_SOURCE_INFO
{
public LUID adapterId;
public uint id;
public uint modeInfoIdx;
public DISPLAYCONFIG_SOURCE_FLAGS statusFlags;
}
[StructLayout(LayoutKind.Sequential)]
private struct DISPLAYCONFIG_PATH_TARGET_INFO
{
public LUID adapterId;
public uint id;
public uint modeInfoIdx;
public DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology;
public DISPLAYCONFIG_ROTATION rotation;
public DISPLAYCONFIG_SCALING scaling;
public DISPLAYCONFIG_RATIONAL refreshRate;
public DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;
public bool targetAvailable;
public DISPLAYCONFIG_TARGET_FLAGS statusFlags;
}
[StructLayout(LayoutKind.Sequential)]
private struct DISPLAYCONFIG_PATH_INFO
{
public DISPLAYCONFIG_PATH_SOURCE_INFO sourceInfo;
public DISPLAYCONFIG_PATH_TARGET_INFO targetInfo;
public DISPLAYCONFIG_PATH flags;
}
[StructLayout(LayoutKind.Sequential)]
private struct DISPLAYCONFIG_MODE_INFO
{
public DISPLAYCONFIG_MODE_INFO_TYPE infoType;
public uint id;
public LUID adapterId;
public DISPLAYCONFIG_MODE_INFO_union info;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct DISPLAYCONFIG_SOURCE_DEVICE_NAME
{
public DISPLAYCONFIG_DEVICE_INFO_HEADER header;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string viewGdiDeviceName;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS
{
public uint value;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct DISPLAYCONFIG_TARGET_DEVICE_NAME
{
public DISPLAYCONFIG_DEVICE_INFO_HEADER header;
public DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS flags;
public DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY 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 monitorDevicePat;
}
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
[DllImport("user32")]
private static extern int GetDisplayConfigBufferSizes(QDC flags, out int numPathArrayElements, out int numModeInfoArrayElements);
[DllImport("user32")]
private static extern int QueryDisplayConfig(QDC flags, ref int numPathArrayElements, [In, Out] DISPLAYCONFIG_PATH_INFO[] pathArray, ref int numModeInfoArrayElements, [In, Out] DISPLAYCONFIG_MODE_INFO[] modeInfoArray, out DISPLAYCONFIG_TOPOLOGY_ID currentTopologyId);
[DllImport("user32")]
private static extern int QueryDisplayConfig(QDC flags, ref int numPathArrayElements, [In, Out] DISPLAYCONFIG_PATH_INFO[] pathArray, ref int numModeInfoArrayElements, [In, Out] DISPLAYCONFIG_MODE_INFO[] modeInfoArray, IntPtr currentTopologyId);
[DllImport("user32")]
private static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO requestPacket);
[DllImport("user32")]
private static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_SOURCE_DEVICE_NAME requestPacket);
[DllImport("user32")]
private static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_TARGET_DEVICE_NAME requestPacket);
I'm trying to replace the 'è' character with the 'È' character globally on my computer.
Referring to many answers here on SO Like this I succesfully created a program that replaces for example an 'A' with a 'E' or any other "normal" character. But if I try to pass the È char it doesn't work as expected.
I'm not trying to replace only internally to my app, but globally on every computer click.
This is what I'm doing:
Form1.cs
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Hide();
KeyInterceptor hook = new KeyInterceptor((int)KeyInterceptor.Modifiers.None, 186, this);
hook.Register();
}
protected override void WndProc(ref Message m)
{
Console.WriteLine(m.Msg);
if (m.Msg == 0x0312)
HandleHotkey(); // è, which was registered before, was pressed
base.WndProc(ref m);
}
private void HandleHotkey()
{
// instead of è send È
KeyboardManager.PressKey(459007);
}
}
KeyInterceptor.cs
class KeyInterceptor
{
[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
public enum Modifiers
{
None = 0x0000,
Alt = 0x0001,
Control = 0x0002,
Shift = 0x0004,
Win = 0x0008
}
int modifier;
int key;
IntPtr hWnd;
int id;
public KeyInterceptor(int modifiers, Keys key, Form f)
{
this.modifier = modifiers;
this.key = (int)key;
this.hWnd = f.Handle;
id = this.GetHashCode();
}
public KeyInterceptor(int modifiers, char key, Form f)
{
this.modifier = modifiers;
this.key = (int)key;
this.hWnd = f.Handle;
id = this.GetHashCode();
}
public KeyInterceptor(int modifiers, int key, Form f)
{
this.modifier = modifiers;
this.key = key;
this.hWnd = f.Handle;
id = this.GetHashCode();
}
public override int GetHashCode()
{
return modifier ^ key ^ hWnd.ToInt32();
}
public bool Register()
{
return RegisterHotKey(hWnd, id, modifier, key);
}
public bool Unregister()
{
return UnregisterHotKey(hWnd, id);
}
}
KeyboardManager.cs
public class KeyboardManager
{
public const int INPUT_KEYBOARD = 1;
public const int KEYEVENTF_KEYUP = 0x0002;
public struct KEYDBINPUT
{
public Int16 wVk;
public ushort wScan;
public Int32 dwFlags;
public Int32 time;
public Int32 dwExtraInfo;
public Int32 __filler1;
public Int32 __filler2;
}
public struct INPUT
{
public Int32 type;
public KEYDBINPUT ki;
}
[DllImport("user32.dll")]
public static extern int SendInput(int cInputs, ref INPUT pInputs, int cbSize);
public static void HoldKey(Keys vk)
{
INPUT input = new INPUT();
input.type = INPUT_KEYBOARD;
input.ki.dwFlags = 0;
input.ki.wVk = (Int16)vk;
SendInput(1, ref input, Marshal.SizeOf(input));
}
public static void ReleaseKey(Keys vk)
{
INPUT input = new INPUT();
input.type = INPUT_KEYBOARD;
input.ki.dwFlags = KEYEVENTF_KEYUP;
input.ki.wVk = (Int16)vk;
SendInput(1, ref input, Marshal.SizeOf(input));
}
public static void HoldKey(int vk)
{
INPUT input = new INPUT();
input.type = INPUT_KEYBOARD;
input.ki.dwFlags = 0;
input.ki.wVk = (Int16)vk;
SendInput(1, ref input, Marshal.SizeOf(input));
}
public static void ReleaseKey(int vk)
{
INPUT input = new INPUT();
input.type = INPUT_KEYBOARD;
input.ki.dwFlags = KEYEVENTF_KEYUP;
input.ki.wVk = (Int16)vk;
SendInput(1, ref input, Marshal.SizeOf(input));
}
public static void PressKey(Keys vk)
{
HoldKey(vk);
ReleaseKey(vk);
}
public static void PressKey(int vk)
{
HoldKey(vk);
ReleaseKey(vk);
}
}
What am I missing? I don't really get how to send that key out.
I trying to fill Wacom tablet screen with my application. How can I find this screen working area?
At this moment I just trying to find this screen by Device Friendly name using ScreenInterrogatory class (code below), but it requires me to know device name. I looking for a way to do this for any Wacom device without knowing the device name (using Wintab api).
//
public Screen GetWacomWorkingArea(string wacomDeviceName)
{
foreach(var screen in System.Windows.Forms.Screen.AllScreens)
{
if(screen.DeviceFriendlyName == wacomDeviceName)
{
return screen.WorkingArea;
}
}
}
//
public static class ScreenInterrogatory
{
public const int ERROR_SUCCESS = 0;
#region enums
public enum QUERY_DEVICE_CONFIG_FLAGS : uint
{
QDC_ALL_PATHS = 0x00000001,
QDC_ONLY_ACTIVE_PATHS = 0x00000002,
QDC_DATABASE_CURRENT = 0x00000004
}
public enum DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY : uint
{
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER = 0xFFFFFFFF,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15 = 0,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SVIDEO = 1,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPOSITE_VIDEO = 2,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPONENT_VIDEO = 3,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI = 4,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI = 5,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_LVDS = 6,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_D_JPN = 8,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDI = 9,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL = 10,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED = 11,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EXTERNAL = 12,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED = 13,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDTVDONGLE = 14,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_MIRACAST = 15,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL = 0x80000000,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_FORCE_UINT32 = 0xFFFFFFFF
}
public enum DISPLAYCONFIG_SCANLINE_ORDERING : uint
{
DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED = 0,
DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE = 1,
DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED = 2,
DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_UPPERFIELDFIRST = DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED,
DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_LOWERFIELDFIRST = 3,
DISPLAYCONFIG_SCANLINE_ORDERING_FORCE_UINT32 = 0xFFFFFFFF
}
public enum DISPLAYCONFIG_ROTATION : uint
{
DISPLAYCONFIG_ROTATION_IDENTITY = 1,
DISPLAYCONFIG_ROTATION_ROTATE90 = 2,
DISPLAYCONFIG_ROTATION_ROTATE180 = 3,
DISPLAYCONFIG_ROTATION_ROTATE270 = 4,
DISPLAYCONFIG_ROTATION_FORCE_UINT32 = 0xFFFFFFFF
}
public enum DISPLAYCONFIG_SCALING : uint
{
DISPLAYCONFIG_SCALING_IDENTITY = 1,
DISPLAYCONFIG_SCALING_CENTERED = 2,
DISPLAYCONFIG_SCALING_STRETCHED = 3,
DISPLAYCONFIG_SCALING_ASPECTRATIOCENTEREDMAX = 4,
DISPLAYCONFIG_SCALING_CUSTOM = 5,
DISPLAYCONFIG_SCALING_PREFERRED = 128,
DISPLAYCONFIG_SCALING_FORCE_UINT32 = 0xFFFFFFFF
}
public enum DISPLAYCONFIG_PIXELFORMAT : uint
{
DISPLAYCONFIG_PIXELFORMAT_8BPP = 1,
DISPLAYCONFIG_PIXELFORMAT_16BPP = 2,
DISPLAYCONFIG_PIXELFORMAT_24BPP = 3,
DISPLAYCONFIG_PIXELFORMAT_32BPP = 4,
DISPLAYCONFIG_PIXELFORMAT_NONGDI = 5,
DISPLAYCONFIG_PIXELFORMAT_FORCE_UINT32 = 0xffffffff
}
public enum DISPLAYCONFIG_MODE_INFO_TYPE : uint
{
DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE = 1,
DISPLAYCONFIG_MODE_INFO_TYPE_TARGET = 2,
DISPLAYCONFIG_MODE_INFO_TYPE_FORCE_UINT32 = 0xFFFFFFFF
}
public enum DISPLAYCONFIG_DEVICE_INFO_TYPE : uint
{
DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME = 1,
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME = 2,
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE = 3,
DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME = 4,
DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_PERSISTENCE = 5,
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_BASE_TYPE = 6,
DISPLAYCONFIG_DEVICE_INFO_FORCE_UINT32 = 0xFFFFFFFF
}
#endregion
#region structs
[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
public uint LowPart;
public int HighPart;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_PATH_SOURCE_INFO
{
public LUID adapterId;
public uint id;
public uint modeInfoIdx;
public uint statusFlags;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_PATH_TARGET_INFO
{
public LUID adapterId;
public uint id;
public uint modeInfoIdx;
private DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology;
private DISPLAYCONFIG_ROTATION rotation;
private DISPLAYCONFIG_SCALING scaling;
private DISPLAYCONFIG_RATIONAL refreshRate;
private DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;
public bool targetAvailable;
public uint statusFlags;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_RATIONAL
{
public uint Numerator;
public uint Denominator;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_PATH_INFO
{
public DISPLAYCONFIG_PATH_SOURCE_INFO sourceInfo;
public DISPLAYCONFIG_PATH_TARGET_INFO targetInfo;
public uint flags;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_2DREGION
{
public uint cx;
public uint cy;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_VIDEO_SIGNAL_INFO
{
public ulong pixelRate;
public DISPLAYCONFIG_RATIONAL hSyncFreq;
public DISPLAYCONFIG_RATIONAL vSyncFreq;
public DISPLAYCONFIG_2DREGION activeSize;
public DISPLAYCONFIG_2DREGION totalSize;
public uint videoStandard;
public DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_TARGET_MODE
{
public DISPLAYCONFIG_VIDEO_SIGNAL_INFO targetVideoSignalInfo;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINTL
{
private int x;
private int y;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_SOURCE_MODE
{
public uint width;
public uint height;
public DISPLAYCONFIG_PIXELFORMAT pixelFormat;
public POINTL position;
}
[StructLayout(LayoutKind.Explicit)]
public struct DISPLAYCONFIG_MODE_INFO_UNION
{
[FieldOffset(0)]
public DISPLAYCONFIG_TARGET_MODE targetMode;
[FieldOffset(0)]
public DISPLAYCONFIG_SOURCE_MODE sourceMode;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_MODE_INFO
{
public DISPLAYCONFIG_MODE_INFO_TYPE infoType;
public uint id;
public LUID adapterId;
public DISPLAYCONFIG_MODE_INFO_UNION modeInfo;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS
{
public uint value;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_DEVICE_INFO_HEADER
{
public DISPLAYCONFIG_DEVICE_INFO_TYPE type;
public uint size;
public LUID adapterId;
public uint id;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct DISPLAYCONFIG_TARGET_DEVICE_NAME
{
public DISPLAYCONFIG_DEVICE_INFO_HEADER header;
public DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS flags;
public DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY 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;
}
#endregion
#region DLL-Imports
[DllImport("user32.dll")]
public static extern int GetDisplayConfigBufferSizes(
QUERY_DEVICE_CONFIG_FLAGS flags, out uint numPathArrayElements, out uint numModeInfoArrayElements);
[DllImport("user32.dll")]
public static extern int QueryDisplayConfig(
QUERY_DEVICE_CONFIG_FLAGS flags,
ref uint numPathArrayElements, [Out] DISPLAYCONFIG_PATH_INFO[] PathInfoArray,
ref uint numModeInfoArrayElements, [Out] DISPLAYCONFIG_MODE_INFO[] ModeInfoArray,
IntPtr currentTopologyId
);
[DllImport("user32.dll")]
public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_TARGET_DEVICE_NAME deviceName);
#endregion
private static string MonitorFriendlyName(LUID adapterId, uint targetId)
{
var deviceName = new DISPLAYCONFIG_TARGET_DEVICE_NAME
{
header =
{
size = (uint)Marshal.SizeOf(typeof (DISPLAYCONFIG_TARGET_DEVICE_NAME)),
adapterId = adapterId,
id = targetId,
type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME
}
};
var error = DisplayConfigGetDeviceInfo(ref deviceName);
if (error != ERROR_SUCCESS)
throw new Win32Exception(error);
return deviceName.monitorFriendlyDeviceName;
}
private static IEnumerable<string> GetAllMonitorsFriendlyNames()
{
uint pathCount, modeCount;
var error = GetDisplayConfigBufferSizes(QUERY_DEVICE_CONFIG_FLAGS.QDC_ONLY_ACTIVE_PATHS, out pathCount, out modeCount);
if (error != ERROR_SUCCESS)
throw new Win32Exception(error);
var displayPaths = new DISPLAYCONFIG_PATH_INFO[pathCount];
var displayModes = new DISPLAYCONFIG_MODE_INFO[modeCount];
error = QueryDisplayConfig(QUERY_DEVICE_CONFIG_FLAGS.QDC_ONLY_ACTIVE_PATHS,
ref pathCount, displayPaths, ref modeCount, displayModes, IntPtr.Zero);
if (error != ERROR_SUCCESS)
throw new Win32Exception(error);
for (var i = 0; i < modeCount; i++)
if (displayModes[i].infoType == DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_TARGET)
yield return MonitorFriendlyName(displayModes[i].adapterId, displayModes[i].id);
}
public static string DeviceFriendlyName(this Screen screen)
{
var allFriendlyNames = GetAllMonitorsFriendlyNames();
for (var index = 0; index < Screen.AllScreens.Length; index++)
if (Equals(screen, Screen.AllScreens[index]))
return allFriendlyNames.ToArray()[index];
return null;
}
}
i am working on listing installed drivers in system as in Device manager.
I got that list from Win32_PnPSignedDriver but it does not provide icons. Is there any way to find that or i have to add custom icons for the list. I want to generate output Like same as in Device manager.I found some reference in C/C++ but not in c#.
Here are two utility classes DeviceClass and Device that demonstrate how to do it. They don't use WMI, but the setupapi with p/invoke (and the System.Drawing's Icon class). I think this API is the only supported way to get the icon. You could then use WMI (using ids, and class ids to get more information this time using WMI).
Here is a comparison using these classes, in a Windows Form, and the Device Manager, as you see it's pretty close, but the class icon is not exactly the same, I don't know why, I've not investigated.
Last note: as expected, some devices have an icon that is different from their class and different from other icons in the same class. We can observe that in the first Audio class, the two devices don't have the same icon.
Here is the code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// This is a standard Form. I have added a TreeView control and an ImageList to the Form.
// The image list is bound to the treeview, with ColorDepth set to Depth32Bit
var classes = DeviceClass.Load(DeviceFiter.AllClasses | DeviceFiter.Present);
foreach (var cls in classes)
{
var classNode = treeView1.Nodes.Add(cls.Description);
imageList1.Images.Add(cls.Icon);
classNode.ImageIndex = imageList1.Images.Count - 1;
classNode.SelectedImageIndex = classNode.ImageIndex;
foreach (var device in cls.Devices)
{
var deviceNode = classNode.Nodes.Add(device.Name);
imageList1.Images.Add(device.Icon);
deviceNode.ImageIndex = imageList1.Images.Count - 1;
deviceNode.SelectedImageIndex = deviceNode.ImageIndex;
}
classNode.Expand();
}
// dispose (icons)
foreach (var cls in classes)
{
foreach (var device in cls.Devices)
{
device.Dispose();
}
cls.Dispose();
}
}
}
public class DeviceClass : IDisposable, IComparable, IComparable<DeviceClass>
{
private List<Device> _devices = new List<Device>();
private Icon _icon;
internal DeviceClass(Guid classId, string description)
{
ClassId = classId;
Description = description;
}
public Guid ClassId { get; }
public string Description { get; }
public Icon Icon => _icon;
public IReadOnlyList<Device> Devices => _devices;
public static IReadOnlyList<DeviceClass> Load(DeviceFiter fiter)
{
var list = new List<DeviceClass>();
var hdevinfo = SetupDiGetClassDevs(IntPtr.Zero, null, IntPtr.Zero, fiter);
try
{
var data = new SP_DEVINFO_DATA();
data.cbSize = Marshal.SizeOf<SP_DEVINFO_DATA>();
int index = 0;
while (SetupDiEnumDeviceInfo(hdevinfo, index, ref data))
{
index++;
var classId = GetGuidProperty(hdevinfo, ref data, DEVPKEY_Device_ClassGuid);
if (classId == Guid.Empty)
continue;
string classDescription = GetClassDescription(classId);
var cls = list.FirstOrDefault(c => c.ClassId == classId);
if (cls == null)
{
cls = new DeviceClass(classId, classDescription);
list.Add(cls);
SetupDiLoadClassIcon(ref classId, out IntPtr clsIcon, out int mini);
if (clsIcon != IntPtr.Zero)
{
cls._icon = Icon.FromHandle(clsIcon);
}
}
string name = GetStringProperty(hdevinfo, ref data, DEVPKEY_Device_FriendlyName);
if (string.IsNullOrWhiteSpace(name))
{
name = GetStringProperty(hdevinfo, ref data, DEVPKEY_Device_DeviceDesc);
}
Icon icon = null;
SetupDiLoadDeviceIcon(hdevinfo, ref data, 16, 16, 0, out IntPtr devIcon);
if (devIcon != IntPtr.Zero)
{
icon = Icon.FromHandle(devIcon);
}
var dev = new Device(cls, name, icon);
cls._devices.Add(dev);
}
}
finally
{
if (hdevinfo != IntPtr.Zero)
{
SetupDiDestroyDeviceInfoList(hdevinfo);
}
}
foreach (var cls in list)
{
cls._devices.Sort();
}
list.Sort();
return list;
}
int IComparable.CompareTo(object obj) => CompareTo(obj as DeviceClass);
public int CompareTo(DeviceClass other)
{
if (other == null)
throw new ArgumentNullException(nameof(other));
return Description.CompareTo(other.Description);
}
public void Dispose()
{
if (_icon != null)
{
_icon.Dispose();
_icon = null;
}
}
private static string GetClassDescription(Guid classId)
{
SetupDiGetClassDescription(ref classId, IntPtr.Zero, 0, out int size);
if (size == 0)
return null;
var ptr = Marshal.AllocCoTaskMem(size * 2);
try
{
if (!SetupDiGetClassDescription(ref classId, ptr, size, out size))
throw new Win32Exception(Marshal.GetLastWin32Error());
return Marshal.PtrToStringUni(ptr, size - 1);
}
finally
{
Marshal.FreeCoTaskMem(ptr);
}
}
private static string GetStringProperty(IntPtr hdevinfo, ref SP_DEVINFO_DATA data, DEVPROPKEY pk)
{
SetupDiGetDeviceProperty(hdevinfo, ref data, ref pk, out int propertyType, IntPtr.Zero, 0, out int size, 0);
if (size == 0)
return null;
var ptr = Marshal.AllocCoTaskMem(size);
try
{
if (!SetupDiGetDeviceProperty(hdevinfo, ref data, ref pk, out propertyType, ptr, size, out size, 0))
throw new Win32Exception(Marshal.GetLastWin32Error());
return Marshal.PtrToStringUni(ptr, (size / 2) - 1);
}
finally
{
Marshal.FreeCoTaskMem(ptr);
}
}
private static Guid GetGuidProperty(IntPtr hdevinfo, ref SP_DEVINFO_DATA data, DEVPROPKEY pk)
{
SetupDiGetDeviceProperty(hdevinfo, ref data, ref pk, out int propertyType, out Guid guid, 16, out int size, 0);
return guid;
}
[StructLayout(LayoutKind.Sequential)]
private struct SP_DEVINFO_DATA
{
public int cbSize;
public Guid ClassGuid;
public int DevInst;
public IntPtr Reserved;
}
[StructLayout(LayoutKind.Sequential)]
private struct DEVPROPKEY
{
public Guid fmtid;
public int pid;
}
private const int ERROR_NOT_FOUND = 118;
private const int ERROR_INSUFFICIENT_BUFFER = 122;
private static readonly DEVPROPKEY DEVPKEY_Device_DeviceDesc = new DEVPROPKEY { fmtid = new Guid("a45c254e-df1c-4efd-8020-67d146a850e0"), pid = 2 };
private static readonly DEVPROPKEY DEVPKEY_Device_FriendlyName = new DEVPROPKEY { fmtid = new Guid("a45c254e-df1c-4efd-8020-67d146a850e0"), pid = 14 };
private static readonly DEVPROPKEY DEVPKEY_Device_Class = new DEVPROPKEY { fmtid = new Guid("a45c254e-df1c-4efd-8020-67d146a850e0"), pid = 9 };
private static readonly DEVPROPKEY DEVPKEY_Device_ClassGuid = new DEVPROPKEY { fmtid = new Guid("a45c254e-df1c-4efd-8020-67d146a850e0"), pid = 10 };
[DllImport("setupapi", CharSet = CharSet.Unicode)]
private static extern IntPtr SetupDiGetClassDevs(IntPtr ClassGuid, [MarshalAs(UnmanagedType.LPWStr)] string Enumerator, IntPtr hwndParent, DeviceFiter Flags);
[DllImport("setupapi", SetLastError = true)]
private static extern bool SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);
[DllImport("setupapi", SetLastError = true)]
private static extern bool SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet, int MemberIndex, ref SP_DEVINFO_DATA DeviceInfoData);
[DllImport("setupapi", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool SetupDiGetClassDescription(ref Guid ClassGuid, IntPtr ClassDescription, int ClassDescriptionSize, out int RequiredSize);
[DllImport("setupapi", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool SetupDiLoadClassIcon(ref Guid ClassGuid, out IntPtr LargeIcon, out int MiniIconIndex);
[DllImport("setupapi", SetLastError = true)]
private static extern bool SetupDiLoadDeviceIcon(IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData,
int cxIcon, int cyIcon, int Flags, out IntPtr hIcon);
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool SetupDiGetDeviceProperty(IntPtr DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData,
ref DEVPROPKEY PropertyKey,
out int PropertyType,
IntPtr PropertyBuffer,
int PropertyBufferSize,
out int RequiredSize,
int Flags);
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool SetupDiGetDeviceProperty(IntPtr DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData,
ref DEVPROPKEY PropertyKey,
out int PropertyType,
out Guid PropertyBuffer,
int PropertyBufferSize,
out int RequiredSize,
int Flags);
}
[Flags]
public enum DeviceFiter // DIGCF_* flags
{
Default = 1,
Present = 2,
AllClasses = 4,
Profile = 8,
DeviceInterface = 16
}
public class Device : IDisposable, IComparable, IComparable<Device>
{
internal Device(DeviceClass cls, string name, Icon icon)
{
Class = cls;
Name = name;
Icon = icon;
}
public string Name { get; }
public DeviceClass Class { get; }
public Icon Icon { get; private set; }
public override string ToString() => Name;
public void Dispose()
{
if (Icon != null)
{
Icon.Dispose();
Icon = null;
}
}
int IComparable.CompareTo(object obj) => CompareTo(obj as Device);
public int CompareTo(Device other)
{
if (other == null)
throw new ArgumentNullException(nameof(other));
return Name.CompareTo(other.Name);
}
}
There is a nice article using SHGetFileInfo function to get associated icons, i'd recommend looking into that.
You cannot do it using pure .Net or C# you will need this dll in the article.
EDIT
Maybe this MDSN Device Information will be of help
I think many of us having some errors with #Simon's codes.
Here are his revised codes:
public class DeviceClass : IDisposable, IComparable, IComparable<DeviceClass>
{
private List<Device> _devices = new List<Device>();
private Icon _icon;
internal DeviceClass(Guid classId, string description)
{
ClassId = classId;
Description = description;
}
public Guid ClassId { get; }
public string Description { get; }
public Icon Icon => _icon;
public IReadOnlyList<Device> Devices => _devices;
public static IReadOnlyList<DeviceClass> Load(DeviceFiter fiter)
{
var list = new List<DeviceClass>();
var hdevinfo = SetupDiGetClassDevs(IntPtr.Zero, null, IntPtr.Zero, fiter);
try
{
var data = new SP_DEVINFO_DATA();
data.cbSize = System.Runtime.InteropServices.Marshal.SizeOf<SP_DEVINFO_DATA>();
int index = 0;
while (SetupDiEnumDeviceInfo(hdevinfo, index, ref data))
{
index++;
var classId = GetGuidProperty(hdevinfo, ref data, DEVPKEY_Device_ClassGuid);
if (classId == Guid.Empty)
continue;
string classDescription = GetClassDescription(classId);
var cls = list.FirstOrDefault(c => c.ClassId == classId);
if (cls == null)
{
cls = new DeviceClass(classId, classDescription);
list.Add(cls);
IntPtr clsIcon;
int mini;
SetupDiLoadClassIcon(ref classId, out clsIcon, out mini);
if (clsIcon != IntPtr.Zero)
{
cls._icon = Icon.FromHandle(clsIcon);
}
}
string name = GetStringProperty(hdevinfo, ref data, DEVPKEY_Device_FriendlyName);
if (string.IsNullOrWhiteSpace(name))
{
name = GetStringProperty(hdevinfo, ref data, DEVPKEY_Device_DeviceDesc);
}
Icon icon = null;
IntPtr devIcon;
SetupDiLoadDeviceIcon(hdevinfo, ref data, 16, 16, 0, out devIcon);
if (devIcon != IntPtr.Zero)
{
icon = Icon.FromHandle(devIcon);
}
var dev = new Device(cls, name, icon);
cls._devices.Add(dev);
}
}
finally
{
if (hdevinfo != IntPtr.Zero)
{
SetupDiDestroyDeviceInfoList(hdevinfo);
}
}
foreach (var cls in list)
{
cls._devices.Sort();
}
list.Sort();
return list;
}
int IComparable.CompareTo(object obj) => CompareTo(obj as DeviceClass);
public int CompareTo(DeviceClass other)
{
if (other == null)
throw new ArgumentNullException(nameof(other));
return Description.CompareTo(other.Description);
}
public void Dispose()
{
if (_icon != null)
{
_icon.Dispose();
_icon = null;
}
}
private static string GetClassDescription(Guid classId)
{
int size = 0;
SetupDiGetClassDescription(ref classId, IntPtr.Zero, 0, out size);
if (size == 0)
return null;
var ptr = Marshal.AllocCoTaskMem(size * 2);
try
{
if (!SetupDiGetClassDescription(ref classId, ptr, size, out size))
throw new Win32Exception(Marshal.GetLastWin32Error());
return Marshal.PtrToStringUni(ptr, size - 1);
}
finally
{
Marshal.FreeCoTaskMem(ptr);
}
}
private static string GetStringProperty(IntPtr hdevinfo, ref SP_DEVINFO_DATA data, DEVPROPKEY pk)
{
int propertyType;
int size;
SetupDiGetDeviceProperty(hdevinfo, ref data, ref pk, out propertyType, IntPtr.Zero, 0, out size, 0);
if (size == 0)
return null;
var ptr = Marshal.AllocCoTaskMem(size);
try
{
if (!SetupDiGetDeviceProperty(hdevinfo, ref data, ref pk, out propertyType, ptr, size, out size, 0))
throw new Win32Exception(Marshal.GetLastWin32Error());
return Marshal.PtrToStringUni(ptr, (size / 2) - 1);
}
finally
{
Marshal.FreeCoTaskMem(ptr);
}
}
private static Guid GetGuidProperty(IntPtr hdevinfo, ref SP_DEVINFO_DATA data, DEVPROPKEY pk)
{
int propertyType, size;
Guid guid;
SetupDiGetDeviceProperty(hdevinfo, ref data, ref pk, out propertyType, out guid, 16, out size, 0);
return guid;
}
[StructLayout(LayoutKind.Sequential)]
private struct SP_DEVINFO_DATA
{
public int cbSize;
public Guid ClassGuid;
public int DevInst;
public IntPtr Reserved;
}
[StructLayout(LayoutKind.Sequential)]
private struct DEVPROPKEY
{
public Guid fmtid;
public int pid;
}
private const int ERROR_NOT_FOUND = 118;
private const int ERROR_INSUFFICIENT_BUFFER = 122;
private static readonly DEVPROPKEY DEVPKEY_Device_DeviceDesc = new DEVPROPKEY { fmtid = new Guid("a45c254e-df1c-4efd-8020-67d146a850e0"), pid = 2 };
private static readonly DEVPROPKEY DEVPKEY_Device_FriendlyName = new DEVPROPKEY { fmtid = new Guid("a45c254e-df1c-4efd-8020-67d146a850e0"), pid = 14 };
private static readonly DEVPROPKEY DEVPKEY_Device_Class = new DEVPROPKEY { fmtid = new Guid("a45c254e-df1c-4efd-8020-67d146a850e0"), pid = 9 };
private static readonly DEVPROPKEY DEVPKEY_Device_ClassGuid = new DEVPROPKEY { fmtid = new Guid("a45c254e-df1c-4efd-8020-67d146a850e0"), pid = 10 };
[DllImport("setupapi", CharSet = CharSet.Unicode)]
private static extern IntPtr SetupDiGetClassDevs(IntPtr ClassGuid, [MarshalAs(UnmanagedType.LPWStr)] string Enumerator, IntPtr hwndParent, DeviceFiter Flags);
[DllImport("setupapi", SetLastError = true)]
private static extern bool SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);
[DllImport("setupapi", SetLastError = true)]
private static extern bool SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet, int MemberIndex, ref SP_DEVINFO_DATA DeviceInfoData);
[DllImport("setupapi", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool SetupDiGetClassDescription(ref Guid ClassGuid, IntPtr ClassDescription, int ClassDescriptionSize, out int RequiredSize);
[DllImport("setupapi", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool SetupDiLoadClassIcon(ref Guid ClassGuid, out IntPtr LargeIcon, out int MiniIconIndex);
[DllImport("setupapi", SetLastError = true)]
private static extern bool SetupDiLoadDeviceIcon(IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData,
int cxIcon, int cyIcon, int Flags, out IntPtr hIcon);
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool SetupDiGetDeviceProperty(IntPtr DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData,
ref DEVPROPKEY PropertyKey,
out int PropertyType,
IntPtr PropertyBuffer,
int PropertyBufferSize,
out int RequiredSize,
int Flags);
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool SetupDiGetDeviceProperty(IntPtr DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData,
ref DEVPROPKEY PropertyKey,
out int PropertyType,
out Guid PropertyBuffer,
int PropertyBufferSize,
out int RequiredSize,
int Flags);
}
[Flags]
public enum DeviceFiter // DIGCF_* flags
{
Default = 1,
Present = 2,
AllClasses = 4,
Profile = 8,
DeviceInterface = 16
}
public class Device : IDisposable, IComparable, IComparable<Device>
{
internal Device(DeviceClass cls, string name, Icon icon)
{
Class = cls;
Name = name;
Icon = icon;
}
public string Name { get; }
public DeviceClass Class { get; }
public Icon Icon { get; private set; }
public override string ToString() => Name;
public void Dispose()
{
if (Icon != null)
{
Icon.Dispose();
Icon = null;
}
}
int IComparable.CompareTo(object obj) => CompareTo(obj as Device);
public int CompareTo(Device other)
{
if (other == null)
throw new ArgumentNullException(nameof(other));
return Name.CompareTo(other.Name);
}
}
how can I change screen resolution programmatically in WPF?
And how can I get a list of available resolutions for display?
I tried have a go at the example described in this article: http://www.c-sharpcorner.com/UploadFile/Joshy_geo/changescreenresolution10102006112110AM/changescreenresolution.aspx But Screen and Resolution classes do not exist in the System.Diagnostics namespace.
C#/WPF
Thanx.
Sorry for the trouble. I found the solution for Windows Forms and made minor changes.
WPF Solution
Place two Listbox (listDevices and listSettings) and Button (btnSave) on the window.
using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
public partial class MainWindow : Window
{
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAY_DEVICE
{
public int cb;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string DeviceName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceString;
public int StateFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceKey;
public DISPLAY_DEVICE(int flags)
{
cb = 0;
StateFlags = flags;
DeviceName = new string((char)32, 32);
DeviceString = new string((char)32, 128);
DeviceID = new string((char)32, 128);
DeviceKey = new string((char)32, 128);
cb = Marshal.SizeOf(this);
}
}
[StructLayout(LayoutKind.Sequential)]
public struct DEVMODE
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public short dmOrientation;
public short dmPaperSize;
public short dmPaperLength;
public short dmPaperWidth;
public short dmScale;
public short dmCopies;
public short dmDefaultSource;
public short dmPrintQuality;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmFormName;
public short dmUnusedPadding;
public short dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmDisplayFlags;
public int dmDisplayFrequency;
}
public MainWindow()
{
InitializeComponent();
EnumDevices();
}
private void listDevices_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
int devNum = listDevices.SelectedIndex;
bool isMain = MainDevice(devNum);
btnSet.IsEnabled = isMain; // enable only for the main device
EnumModes(devNum);
}
private void btnSet_Click(object sender, RoutedEventArgs e)
{ //set selected display mode
int devNum = listDevices.SelectedIndex;
int modeNum = listSettings.SelectedIndex;
DEVMODE d = GetDevmode(devNum, modeNum);
if (d.dmBitsPerPel != 0 & d.dmPelsWidth != 0
& d.dmPelsHeight != 0)
{
ChangeDisplaySettings(ref d, 0);
}
}
private void EnumModes(int devNum)
{
listSettings.Items.Clear();
string devName = GetDeviceName(devNum);
DEVMODE devMode = new DEVMODE();
int modeNum = 0;
bool result = true;
do
{
result = EnumDisplaySettings(devName,
modeNum, ref devMode);
if (result)
{
string item = DevmodeToString(devMode);
listSettings.Items.Add(item);
}
modeNum++;
} while (result);
if (listSettings.Items.Count > 0)
{
DEVMODE current = GetDevmode(devNum, -1);
// int selected = listSettings.FindString(DevmodeToString(current));
int selected = listSettings.Items.IndexOf(DevmodeToString(current));
if (selected >= 0)
{
listSettings.SelectedIndex = selected;
// listSettings.SetSelected(selected, true);
}
}
}
private DEVMODE GetDevmode(int devNum, int modeNum)
{ //populates DEVMODE for the specified device and mode
DEVMODE devMode = new DEVMODE();
string devName = GetDeviceName(devNum);
EnumDisplaySettings(devName, modeNum, ref devMode);
return devMode;
}
private string DevmodeToString(DEVMODE devMode)
{
return devMode.dmPelsWidth.ToString() +
" x " + devMode.dmPelsHeight.ToString() +
", " + devMode.dmBitsPerPel.ToString() +
" bits, " +
devMode.dmDisplayFrequency.ToString() + " Hz";
}
private void EnumDevices()
{ //populates Display Devices list
this.listDevices.Items.Clear();
DISPLAY_DEVICE d = new DISPLAY_DEVICE(0);
int devNum = 0;
bool result;
do
{
result = EnumDisplayDevices(IntPtr.Zero,
devNum, ref d, 0);
if (result)
{
string item = devNum.ToString() +
". " + d.DeviceString.Trim();
if ((d.StateFlags & 4) != 0) item += " - main";
this.listDevices.Items.Add(item);
}
devNum++;
} while (result);
}
private string GetDeviceName(int devNum)
{
DISPLAY_DEVICE d = new DISPLAY_DEVICE(0);
bool result = EnumDisplayDevices(IntPtr.Zero,
devNum, ref d, 0);
return (result ? d.DeviceName.Trim() : "#error#");
}
private bool MainDevice(int devNum)
{ //whether the specified device is the main device
DISPLAY_DEVICE d = new DISPLAY_DEVICE(0);
if (EnumDisplayDevices(IntPtr.Zero, devNum, ref d, 0))
{
return ((d.StateFlags & 4) != 0);
} return false;
}
[DllImport("User32.dll")]
private static extern bool EnumDisplayDevices(
IntPtr lpDevice, int iDevNum,
ref DISPLAY_DEVICE lpDisplayDevice, int dwFlags);
[DllImport("User32.dll")]
private static extern bool EnumDisplaySettings(
string devName, int modeNum, ref DEVMODE devMode);
[DllImport("user32.dll")]
public static extern int ChangeDisplaySettings(
ref DEVMODE devMode, int flags);
}
WPF Screen Resolution Source: http://www.mediafire.com/?ciiymhmc7v28v4y