mirror of
https://github.com/terrymacdonald/DisplayMagician.git
synced 2024-08-30 18:32:20 +00:00
Updated WinLibrary with latest GDI API changes
This will hopefully fix the issues #45 and #46.
This commit is contained in:
parent
a9527ffd6e
commit
4a8acd4b86
@ -85,6 +85,7 @@
|
|||||||
<DependentUpon>DisplayView.cs</DependentUpon>
|
<DependentUpon>DisplayView.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Windows\CCD.cs" />
|
<Compile Include="Windows\CCD.cs" />
|
||||||
|
<Compile Include="Windows\GDI.cs" />
|
||||||
<Compile Include="Windows\WinLibrary.cs" />
|
<Compile Include="Windows\WinLibrary.cs" />
|
||||||
<Compile Include="Wallpaper.cs" />
|
<Compile Include="Wallpaper.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -393,7 +393,7 @@ namespace DisplayMagicianShared.Windows
|
|||||||
public override bool Equals(object obj) => obj is DISPLAYCONFIG_RATIONAL other && this.Equals(other);
|
public override bool Equals(object obj) => obj is DISPLAYCONFIG_RATIONAL other && this.Equals(other);
|
||||||
public bool Equals(DISPLAYCONFIG_RATIONAL other)
|
public bool Equals(DISPLAYCONFIG_RATIONAL other)
|
||||||
=> Numerator == other.Numerator &&
|
=> Numerator == other.Numerator &&
|
||||||
Denominator == other.Denominator;
|
Denominator == other.Denominator;
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
|
675
DisplayMagicianShared/Windows/GDI.cs
Normal file
675
DisplayMagicianShared/Windows/GDI.cs
Normal file
@ -0,0 +1,675 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DisplayMagicianShared.Windows
|
||||||
|
{
|
||||||
|
// 90% of this file is cribbed from WindowsDisplayAPI by Soroush Falahati
|
||||||
|
// The other 10% is from MikedouglasDev's ChangeScreenResolution
|
||||||
|
// https://github.com/mikedouglasdev/changescreenresolution/blob/master/ChangeScreenResolutionSolution/ChangeScreenResolution/SafeNativeMethods.cs
|
||||||
|
// and GemingLeader here: https://www.c-sharpcorner.com/uploadfile/GemingLeader/changing-display-settings-programmatically/
|
||||||
|
|
||||||
|
|
||||||
|
public enum CHANGE_DISPLAY_RESULTS
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Completed successfully
|
||||||
|
/// </summary>
|
||||||
|
Successful = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes needs restart
|
||||||
|
/// </summary>
|
||||||
|
Restart = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Failed to change and save setings
|
||||||
|
/// </summary>
|
||||||
|
Failed = -1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invalid data provided
|
||||||
|
/// </summary>
|
||||||
|
BadMode = -2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes not updated
|
||||||
|
/// </summary>
|
||||||
|
NotUpdated = -3,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invalid flags provided
|
||||||
|
/// </summary>
|
||||||
|
BadFlags = -4,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Bad parameters provided
|
||||||
|
/// </summary>
|
||||||
|
BadParam = -5,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Bad Dual View mode used with mode
|
||||||
|
/// </summary>
|
||||||
|
BadDualView = -6
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum CHANGE_DISPLAY_SETTINGS_FLAGS : UInt32
|
||||||
|
{
|
||||||
|
CDS_NONE = 0,
|
||||||
|
CDS_UPDATEREGISTRY = 0x00000001,
|
||||||
|
CDS_TEST = 0x00000002,
|
||||||
|
CDS_FULLSCREEN = 0x00000004,
|
||||||
|
CDS_GLOBAL = 0x00000008,
|
||||||
|
CDS_SET_PRIMARY = 0x00000010,
|
||||||
|
CDS_VIDEOPARAMETERS = 0x00000020,
|
||||||
|
CDS_ENABLE_UNSAFE_MODES = 0x00000100,
|
||||||
|
CDS_DISABLE_UNSAFE_MODES = 0x00000200,
|
||||||
|
CDS_RESET = 0x40000000,
|
||||||
|
CDS_RESET_EX = 0x20000000,
|
||||||
|
CDS_NORESET = 0x10000000
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum DEVICE_CAPABILITY : Int32
|
||||||
|
{
|
||||||
|
DriverVersion = 0,
|
||||||
|
Technology = 2,
|
||||||
|
HorizontalSizeInMM = 4,
|
||||||
|
VerticalSizeInMM = 6,
|
||||||
|
HorizontalResolution = 8,
|
||||||
|
VerticalResolution = 10,
|
||||||
|
BitsPerPixel = 12,
|
||||||
|
Planes = 14,
|
||||||
|
NumberOfBrushes = 16,
|
||||||
|
NumberOfPens = 18,
|
||||||
|
NumberOfMarkers = 20,
|
||||||
|
NumberOfFonts = 22,
|
||||||
|
NumberOfColors = 24,
|
||||||
|
DeviceDescriptorSize = 26,
|
||||||
|
CurveCapabilities = 28,
|
||||||
|
LineCapabilities = 30,
|
||||||
|
PolygonalCapabilities = 32,
|
||||||
|
TextCapabilities = 34,
|
||||||
|
ClipCapabilities = 36,
|
||||||
|
RasterCapabilities = 38,
|
||||||
|
HorizontalAspect = 40,
|
||||||
|
VerticalAspect = 42,
|
||||||
|
HypotenuseAspect = 44,
|
||||||
|
//ShadeBlendingCapabilities = 45,
|
||||||
|
HorizontalLogicalPixels = 88,
|
||||||
|
VerticalLogicalPixels = 90,
|
||||||
|
PaletteSize = 104,
|
||||||
|
ReservedPaletteSize = 106,
|
||||||
|
ColorResolution = 108,
|
||||||
|
|
||||||
|
// Printer Only
|
||||||
|
PhysicalWidth = 110,
|
||||||
|
PhysicalHeight = 111,
|
||||||
|
PhysicalHorizontalMargin = 112,
|
||||||
|
PhysicalVerticalMargin = 113,
|
||||||
|
HorizontalScalingFactor = 114,
|
||||||
|
VerticalScalingFactor = 115,
|
||||||
|
|
||||||
|
// Display Only
|
||||||
|
VerticalRefreshRateInHz = 116,
|
||||||
|
DesktopVerticalResolution = 117,
|
||||||
|
DesktopHorizontalResolution = 118,
|
||||||
|
PreferredBLTAlignment = 119,
|
||||||
|
ShadeBlendingCapabilities = 120,
|
||||||
|
ColorManagementCapabilities = 121,
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum DEVICE_MODE_FIELDS : UInt32
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Position = 0x20,
|
||||||
|
DisplayOrientation = 0x80,
|
||||||
|
Color = 0x800,
|
||||||
|
Duplex = 0x1000,
|
||||||
|
YResolution = 0x2000,
|
||||||
|
TtOption = 0x4000,
|
||||||
|
Collate = 0x8000,
|
||||||
|
FormName = 0x10000,
|
||||||
|
LogPixels = 0x20000,
|
||||||
|
BitsPerPixel = 0x40000,
|
||||||
|
PelsWidth = 0x80000,
|
||||||
|
PelsHeight = 0x100000,
|
||||||
|
DisplayFlags = 0x200000,
|
||||||
|
DisplayFrequency = 0x400000,
|
||||||
|
DisplayFixedOutput = 0x20000000,
|
||||||
|
AllDisplay = Position |
|
||||||
|
DisplayOrientation |
|
||||||
|
YResolution |
|
||||||
|
BitsPerPixel |
|
||||||
|
PelsWidth |
|
||||||
|
PelsHeight |
|
||||||
|
DisplayFlags |
|
||||||
|
DisplayFrequency |
|
||||||
|
DisplayFixedOutput,
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum DISPLAY_DEVICE_STATE_FLAGS : UInt32
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The device is part of the desktop.
|
||||||
|
/// </summary>
|
||||||
|
AttachedToDesktop = 0x1,
|
||||||
|
MultiDriver = 0x2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The device is part of the desktop.
|
||||||
|
/// </summary>
|
||||||
|
PrimaryDevice = 0x4,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a pseudo device used to mirror application drawing for remoting or other purposes.
|
||||||
|
/// </summary>
|
||||||
|
MirroringDriver = 0x8,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The device is VGA compatible.
|
||||||
|
/// </summary>
|
||||||
|
VGACompatible = 0x10,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The device is removable; it cannot be the primary display.
|
||||||
|
/// </summary>
|
||||||
|
Removable = 0x20,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The device has more display modes than its output devices support.
|
||||||
|
/// </summary>
|
||||||
|
ModesPruned = 0x8000000,
|
||||||
|
Remote = 0x4000000,
|
||||||
|
Disconnect = 0x2000000
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum DISPLAY_FIXED_OUTPUT : UInt32
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Default behavior
|
||||||
|
/// </summary>
|
||||||
|
Default = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stretches the output to fit to the display
|
||||||
|
/// </summary>
|
||||||
|
Stretch = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Centers the output in the middle of the display
|
||||||
|
/// </summary>
|
||||||
|
Center = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum DISPLAY_FLAGS : UInt32
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Grayscale = 1,
|
||||||
|
Interlaced = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum DISPLAY_ORIENTATION : UInt32
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// No rotation
|
||||||
|
/// </summary>
|
||||||
|
Rotate0Degree = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 90 degree rotation
|
||||||
|
/// </summary>
|
||||||
|
Rotate90Degree = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 180 degree rotation
|
||||||
|
/// </summary>
|
||||||
|
Rotate180Degree = 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 270 degree rotation
|
||||||
|
/// </summary>
|
||||||
|
Rotate270Degree = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum DISPLAY_SETTINGS_MODE : Int32
|
||||||
|
{
|
||||||
|
CurrentSettings = -1, // Retrieves current display mode
|
||||||
|
RegistrySettings = -2 // Retrieves current display mode stored within the registry.
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum DISPLAY_TECHNOLOGY : Int32
|
||||||
|
{
|
||||||
|
Plotter = 0,
|
||||||
|
RasterDisplay = 1,
|
||||||
|
RasterPrinter = 2,
|
||||||
|
RasterCamera = 3,
|
||||||
|
CharacterStream = 4,
|
||||||
|
MetaFile = 5,
|
||||||
|
DisplayFile = 6,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum MONITOR_FROM_FLAG : UInt32
|
||||||
|
{
|
||||||
|
DefaultToNull = 0,
|
||||||
|
DefaultToPrimary = 1,
|
||||||
|
DefaultToNearest = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum MONITOR_INFO_FLAGS : UInt32
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Primary = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd183565(v=vs.85).aspx
|
||||||
|
// https://www.c-sharpcorner.com/uploadfile/GemingLeader/changing-display-settings-programmatically/
|
||||||
|
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
|
||||||
|
public struct DEVICE_MODE : IEquatable<DEVICE_MODE>
|
||||||
|
{
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
|
||||||
|
[FieldOffset(0)]
|
||||||
|
public string DeviceName;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.U2)]
|
||||||
|
[FieldOffset(32)]
|
||||||
|
public UInt16 SpecificationVersion;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.U2)]
|
||||||
|
[FieldOffset(34)]
|
||||||
|
public UInt16 DriverVersion;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.U2)]
|
||||||
|
[FieldOffset(36)]
|
||||||
|
public UInt16 Size;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.U2)]
|
||||||
|
[FieldOffset(38)]
|
||||||
|
public UInt16 DriverExtra;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.U4)]
|
||||||
|
[FieldOffset(40)]
|
||||||
|
public DEVICE_MODE_FIELDS Fields;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.Struct)]
|
||||||
|
[FieldOffset(44)]
|
||||||
|
public POINTL Position;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.U4)]
|
||||||
|
[FieldOffset(52)]
|
||||||
|
public DISPLAY_ORIENTATION DisplayOrientation;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.U4)]
|
||||||
|
[FieldOffset(56)]
|
||||||
|
public DISPLAY_FIXED_OUTPUT DisplayFixedOutput;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.I2)]
|
||||||
|
[FieldOffset(60)]
|
||||||
|
public Int16 Color;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.I2)]
|
||||||
|
[FieldOffset(62)]
|
||||||
|
public Int16 Duplex;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.I2)]
|
||||||
|
[FieldOffset(64)]
|
||||||
|
public Int16 YResolution;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.I2)]
|
||||||
|
[FieldOffset(66)]
|
||||||
|
public Int16 TrueTypeOption;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.I2)]
|
||||||
|
[FieldOffset(68)]
|
||||||
|
public Int16 Collate;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
|
||||||
|
[FieldOffset(72)]
|
||||||
|
public string FormName;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.U2)]
|
||||||
|
[FieldOffset(102)]
|
||||||
|
public UInt16 LogicalInchPixels;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.U4)]
|
||||||
|
[FieldOffset(104)]
|
||||||
|
public UInt32 BitsPerPixel;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.U4)]
|
||||||
|
[FieldOffset(108)]
|
||||||
|
public UInt32 PixelsWidth;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.U4)]
|
||||||
|
[FieldOffset(112)]
|
||||||
|
public UInt32 PixelsHeight;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.U4)]
|
||||||
|
[FieldOffset(116)]
|
||||||
|
public DISPLAY_FLAGS DisplayFlags;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.U4)]
|
||||||
|
[FieldOffset(120)]
|
||||||
|
public UInt32 DisplayFrequency;
|
||||||
|
|
||||||
|
public override bool Equals(object obj) => obj is DEVICE_MODE other && this.Equals(other);
|
||||||
|
|
||||||
|
public bool Equals(DEVICE_MODE other)
|
||||||
|
=> DeviceName.Equals(other.DeviceName) &&
|
||||||
|
SpecificationVersion == other.SpecificationVersion &&
|
||||||
|
DriverVersion.Equals(other.DriverVersion) &&
|
||||||
|
Size.Equals(other.Size) &&
|
||||||
|
DriverExtra.Equals(other.DriverExtra) &&
|
||||||
|
Fields.Equals(other.Fields) &&
|
||||||
|
Position.Equals(other.Position) &&
|
||||||
|
DisplayOrientation.Equals(other.DisplayOrientation) &&
|
||||||
|
DisplayFixedOutput.Equals(other.DisplayFixedOutput) &&
|
||||||
|
Color.Equals(other.Color) &&
|
||||||
|
Duplex.Equals(other.Duplex) &&
|
||||||
|
YResolution.Equals(other.YResolution) &&
|
||||||
|
TrueTypeOption.Equals(other.TrueTypeOption) &&
|
||||||
|
Collate.Equals(other.Collate) &&
|
||||||
|
FormName.Equals(other.FormName) &&
|
||||||
|
LogicalInchPixels.Equals(other.LogicalInchPixels) &&
|
||||||
|
BitsPerPixel.Equals(other.BitsPerPixel) &&
|
||||||
|
PixelsWidth.Equals(other.PixelsWidth) &&
|
||||||
|
PixelsHeight.Equals(other.PixelsHeight) &&
|
||||||
|
DisplayFlags.Equals(other.DisplayFlags) &&
|
||||||
|
DisplayFrequency == other.DisplayFrequency;
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return (DeviceName, SpecificationVersion, DriverVersion, Size, DriverExtra, Fields, Position, DisplayOrientation, DisplayFixedOutput, Color, Duplex,
|
||||||
|
YResolution, TrueTypeOption, Collate, FormName, LogicalInchPixels, BitsPerPixel, PixelsWidth, PixelsHeight, DisplayFlags, DisplayFrequency).GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(DEVICE_MODE lhs, DEVICE_MODE rhs) => lhs.Equals(rhs);
|
||||||
|
|
||||||
|
public static bool operator !=(DEVICE_MODE lhs, DEVICE_MODE rhs) => !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||||
|
public struct DISPLAY_DEVICE : IEquatable<DISPLAY_DEVICE>
|
||||||
|
{
|
||||||
|
[MarshalAs(UnmanagedType.U4)]
|
||||||
|
public UInt32 Size;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
|
||||||
|
public string DeviceName;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||||
|
public string DeviceString;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.U4)]
|
||||||
|
public DISPLAY_DEVICE_STATE_FLAGS StateFlags;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||||
|
public string DeviceId;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||||
|
public string DeviceKey;
|
||||||
|
|
||||||
|
public override bool Equals(object obj) => obj is DISPLAY_DEVICE other && this.Equals(other);
|
||||||
|
|
||||||
|
public bool Equals(DISPLAY_DEVICE other)
|
||||||
|
=> Size == other.Size &&
|
||||||
|
DeviceName == other.DeviceName &&
|
||||||
|
DeviceString == other.DeviceString &&
|
||||||
|
StateFlags == other.StateFlags &&
|
||||||
|
DeviceId == other.DeviceId &&
|
||||||
|
DeviceKey == other.DeviceKey;
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return (Size, DeviceName, DeviceString, StateFlags, DeviceId, DeviceKey).GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(DISPLAY_DEVICE lhs, DISPLAY_DEVICE rhs) => lhs.Equals(rhs);
|
||||||
|
|
||||||
|
public static bool operator !=(DISPLAY_DEVICE lhs, DISPLAY_DEVICE rhs) => !(lhs == rhs);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct GAMMA_RAMP : IEquatable<GAMMA_RAMP>
|
||||||
|
{
|
||||||
|
public const int DataPoints = 256;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = DataPoints)]
|
||||||
|
public UInt16[] Red;
|
||||||
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = DataPoints)]
|
||||||
|
public UInt16[] Green;
|
||||||
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = DataPoints)]
|
||||||
|
public UInt16[] Blue;
|
||||||
|
|
||||||
|
public override bool Equals(object obj) => obj is GAMMA_RAMP other && this.Equals(other);
|
||||||
|
|
||||||
|
public bool Equals(GAMMA_RAMP other)
|
||||||
|
=> Red.SequenceEqual(other.Red) &&
|
||||||
|
Green.SequenceEqual(other.Green) &&
|
||||||
|
Blue.SequenceEqual(other.Blue);
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return (Red, Green, Blue).GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(GAMMA_RAMP lhs, GAMMA_RAMP rhs) => lhs.Equals(rhs);
|
||||||
|
|
||||||
|
public static bool operator !=(GAMMA_RAMP lhs, GAMMA_RAMP rhs) => !(lhs == rhs);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct MONITOR_INFO : IEquatable<MONITOR_INFO>
|
||||||
|
{
|
||||||
|
internal UInt32 Size;
|
||||||
|
public RECTL Bounds;
|
||||||
|
public RECTL WorkingArea;
|
||||||
|
public MONITOR_INFO_FLAGS Flags;
|
||||||
|
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
|
||||||
|
public string DisplayName;
|
||||||
|
|
||||||
|
public override bool Equals(object obj) => obj is MONITOR_INFO other && this.Equals(other);
|
||||||
|
|
||||||
|
public bool Equals(MONITOR_INFO other)
|
||||||
|
=> Size == other.Size &&
|
||||||
|
Bounds.Equals(other.Bounds) &&
|
||||||
|
WorkingArea.Equals(other.WorkingArea) &&
|
||||||
|
Flags == other.Flags &&
|
||||||
|
DisplayName == other.DisplayName;
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return (Size, Bounds, WorkingArea, Flags, DisplayName).GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(MONITOR_INFO lhs, MONITOR_INFO rhs) => lhs.Equals(rhs);
|
||||||
|
|
||||||
|
public static bool operator !=(MONITOR_INFO lhs, MONITOR_INFO rhs) => !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct GDI_DISPLAY_SETTING : IEquatable<GDI_DISPLAY_SETTING>
|
||||||
|
{
|
||||||
|
public bool IsEnabled;
|
||||||
|
public bool IsPrimary;
|
||||||
|
public DISPLAY_DEVICE Device;
|
||||||
|
public DEVICE_MODE DeviceMode;
|
||||||
|
|
||||||
|
public override bool Equals(object obj) => obj is GDI_DISPLAY_SETTING other && this.Equals(other);
|
||||||
|
|
||||||
|
public bool Equals(GDI_DISPLAY_SETTING other)
|
||||||
|
=> IsEnabled == other.IsEnabled &&
|
||||||
|
IsPrimary == other.IsPrimary &&
|
||||||
|
Device.Equals(other.Device) &&
|
||||||
|
DeviceMode.Equals(other.DeviceMode);
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return (IsEnabled, IsPrimary, Device, DeviceMode).GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(GDI_DISPLAY_SETTING lhs, GDI_DISPLAY_SETTING rhs) => lhs.Equals(rhs);
|
||||||
|
|
||||||
|
public static bool operator !=(GDI_DISPLAY_SETTING lhs, GDI_DISPLAY_SETTING rhs) => !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal class DCHandle : SafeHandle
|
||||||
|
{
|
||||||
|
private readonly bool _created;
|
||||||
|
|
||||||
|
private DCHandle(IntPtr handle, bool created) : base(handle, true)
|
||||||
|
{
|
||||||
|
_created = created;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsInvalid
|
||||||
|
{
|
||||||
|
get => handle == IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DCHandle CreateFromDevice(string screenName, string devicePath)
|
||||||
|
{
|
||||||
|
return new DCHandle(
|
||||||
|
GDIImport.CreateDC(screenName, devicePath, null, IntPtr.Zero),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DCHandle CreateFromScreen(string screenName)
|
||||||
|
{
|
||||||
|
return CreateFromDevice(screenName, screenName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DCHandle CreateFromWindow(IntPtr windowHandle)
|
||||||
|
{
|
||||||
|
return new DCHandle(
|
||||||
|
GDIImport.GetDC(windowHandle),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DCHandle CreateGlobal()
|
||||||
|
{
|
||||||
|
return new DCHandle(
|
||||||
|
GDIImport.CreateDC("DISPLAY", null, null, IntPtr.Zero),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool ReleaseHandle()
|
||||||
|
{
|
||||||
|
return _created
|
||||||
|
? GDIImport.DeleteDC(this)
|
||||||
|
: GDIImport.ReleaseDC(IntPtr.Zero, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GDIImport
|
||||||
|
{
|
||||||
|
[DllImport("user32", CharSet = CharSet.Ansi)]
|
||||||
|
public static extern CHANGE_DISPLAY_RESULTS ChangeDisplaySettingsEx(
|
||||||
|
string deviceName,
|
||||||
|
ref DEVICE_MODE devMode,
|
||||||
|
IntPtr handler,
|
||||||
|
CHANGE_DISPLAY_SETTINGS_FLAGS flags,
|
||||||
|
IntPtr param
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport("user32", CharSet = CharSet.Ansi)]
|
||||||
|
public static extern CHANGE_DISPLAY_RESULTS ChangeDisplaySettingsEx(
|
||||||
|
string deviceName,
|
||||||
|
IntPtr devModePointer,
|
||||||
|
IntPtr handler,
|
||||||
|
CHANGE_DISPLAY_SETTINGS_FLAGS flags,
|
||||||
|
IntPtr param
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport("user32", CharSet = CharSet.Ansi)]
|
||||||
|
public static extern bool EnumDisplaySettings(
|
||||||
|
string deviceName,
|
||||||
|
DISPLAY_SETTINGS_MODE mode,
|
||||||
|
ref DEVICE_MODE devMode
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport("gdi32", CharSet = CharSet.Unicode)]
|
||||||
|
internal static extern IntPtr CreateDC(string driver, string device, string port, IntPtr deviceMode);
|
||||||
|
|
||||||
|
[DllImport("gdi32")]
|
||||||
|
internal static extern bool DeleteDC(DCHandle dcHandle);
|
||||||
|
|
||||||
|
|
||||||
|
[DllImport("user32", CharSet = CharSet.Unicode)]
|
||||||
|
internal static extern bool EnumDisplayDevices(
|
||||||
|
string deviceName,
|
||||||
|
UInt32 deviceNumber,
|
||||||
|
ref DISPLAY_DEVICE displayDevice,
|
||||||
|
UInt32 flags
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport("user32")]
|
||||||
|
internal static extern bool EnumDisplayMonitors(
|
||||||
|
[In] IntPtr dcHandle,
|
||||||
|
[In] IntPtr clip,
|
||||||
|
MonitorEnumProcedure callback,
|
||||||
|
IntPtr callbackObject
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport("user32")]
|
||||||
|
internal static extern IntPtr GetDC(IntPtr windowHandle);
|
||||||
|
|
||||||
|
[DllImport("gdi32")]
|
||||||
|
internal static extern int GetDeviceCaps(DCHandle dcHandle, DEVICE_CAPABILITY index);
|
||||||
|
|
||||||
|
[DllImport("gdi32")]
|
||||||
|
internal static extern bool GetDeviceGammaRamp(DCHandle dcHandle, ref GAMMA_RAMP ramp);
|
||||||
|
|
||||||
|
[DllImport("user32")]
|
||||||
|
internal static extern bool GetMonitorInfo(
|
||||||
|
IntPtr monitorHandle,
|
||||||
|
ref MONITOR_INFO monitorInfo
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport("user32")]
|
||||||
|
internal static extern IntPtr MonitorFromPoint(
|
||||||
|
[In] POINTL point,
|
||||||
|
MONITOR_FROM_FLAG flag
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport("user32")]
|
||||||
|
internal static extern IntPtr MonitorFromRect(
|
||||||
|
[In] RECTL rectangle,
|
||||||
|
MONITOR_FROM_FLAG flag
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport("user32")]
|
||||||
|
internal static extern IntPtr MonitorFromWindow(
|
||||||
|
[In] IntPtr windowHandle,
|
||||||
|
MONITOR_FROM_FLAG flag
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport("user32")]
|
||||||
|
internal static extern bool ReleaseDC([In] IntPtr windowHandle, [In] DCHandle dcHandle);
|
||||||
|
|
||||||
|
[DllImport("gdi32")]
|
||||||
|
internal static extern bool SetDeviceGammaRamp(DCHandle dcHandle, ref GAMMA_RAMP ramp);
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||||
|
internal delegate int MonitorEnumProcedure(
|
||||||
|
IntPtr monitorHandle,
|
||||||
|
IntPtr dcHandle,
|
||||||
|
ref RECTL rect,
|
||||||
|
IntPtr callbackObject
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ using Microsoft.Win32.SafeHandles;
|
|||||||
using DisplayMagicianShared;
|
using DisplayMagicianShared;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace DisplayMagicianShared.Windows
|
namespace DisplayMagicianShared.Windows
|
||||||
{
|
{
|
||||||
@ -41,6 +42,7 @@ namespace DisplayMagicianShared.Windows
|
|||||||
public DISPLAYCONFIG_PATH_INFO[] DisplayConfigPaths;
|
public DISPLAYCONFIG_PATH_INFO[] DisplayConfigPaths;
|
||||||
public DISPLAYCONFIG_MODE_INFO[] DisplayConfigModes;
|
public DISPLAYCONFIG_MODE_INFO[] DisplayConfigModes;
|
||||||
public ADVANCED_HDR_INFO_PER_PATH[] DisplayHDRStates;
|
public ADVANCED_HDR_INFO_PER_PATH[] DisplayHDRStates;
|
||||||
|
public Dictionary<string, GDI_DISPLAY_SETTING> GdiDisplaySettings;
|
||||||
// Note: We purposely have left out the DisplaySources from the Equals as it's order keeps changing after each reboot and after each profile swap
|
// Note: We purposely have left out the DisplaySources from the Equals as it's order keeps changing after each reboot and after each profile swap
|
||||||
// and it is informational only and doesn't contribute to the configuration (it's used for generating the Screens structure, and therefore for
|
// and it is informational only and doesn't contribute to the configuration (it's used for generating the Screens structure, and therefore for
|
||||||
// generating the profile icon.
|
// generating the profile icon.
|
||||||
@ -52,11 +54,12 @@ namespace DisplayMagicianShared.Windows
|
|||||||
=> DisplayConfigPaths.SequenceEqual(other.DisplayConfigPaths) &&
|
=> DisplayConfigPaths.SequenceEqual(other.DisplayConfigPaths) &&
|
||||||
DisplayConfigModes.SequenceEqual(other.DisplayConfigModes) &&
|
DisplayConfigModes.SequenceEqual(other.DisplayConfigModes) &&
|
||||||
DisplayHDRStates.SequenceEqual(other.DisplayHDRStates) &&
|
DisplayHDRStates.SequenceEqual(other.DisplayHDRStates) &&
|
||||||
|
GdiDisplaySettings.SequenceEqual(other.GdiDisplaySettings) &&
|
||||||
DisplayIdentifiers.SequenceEqual(other.DisplayIdentifiers);
|
DisplayIdentifiers.SequenceEqual(other.DisplayIdentifiers);
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return (DisplayConfigPaths, DisplayConfigModes, DisplayHDRStates).GetHashCode();
|
return (DisplayConfigPaths, DisplayConfigModes, DisplayHDRStates, GdiDisplaySettings, DisplayIdentifiers).GetHashCode();
|
||||||
}
|
}
|
||||||
public static bool operator ==(WINDOWS_DISPLAY_CONFIG lhs, WINDOWS_DISPLAY_CONFIG rhs) => lhs.Equals(rhs);
|
public static bool operator ==(WINDOWS_DISPLAY_CONFIG lhs, WINDOWS_DISPLAY_CONFIG rhs) => lhs.Equals(rhs);
|
||||||
|
|
||||||
@ -128,6 +131,24 @@ namespace DisplayMagicianShared.Windows
|
|||||||
return _instance;
|
return _instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WINDOWS_DISPLAY_CONFIG CreateDefaultConfig()
|
||||||
|
{
|
||||||
|
WINDOWS_DISPLAY_CONFIG myDefaultConfig = new WINDOWS_DISPLAY_CONFIG();
|
||||||
|
|
||||||
|
// Fill in the minimal amount we need to avoid null references
|
||||||
|
// so that we won't break json.net when we save a default config
|
||||||
|
|
||||||
|
myDefaultConfig.DisplayAdapters = new Dictionary<ulong, string>();
|
||||||
|
myDefaultConfig.DisplayConfigModes = new DISPLAYCONFIG_MODE_INFO[0];
|
||||||
|
myDefaultConfig.DisplayConfigPaths = new DISPLAYCONFIG_PATH_INFO[0];
|
||||||
|
myDefaultConfig.DisplayHDRStates = new ADVANCED_HDR_INFO_PER_PATH[0];
|
||||||
|
myDefaultConfig.DisplayIdentifiers = new List<string>();
|
||||||
|
myDefaultConfig.DisplaySources = new Dictionary<string, uint>();
|
||||||
|
myDefaultConfig.GdiDisplaySettings = new Dictionary<string, GDI_DISPLAY_SETTING>();
|
||||||
|
|
||||||
|
return myDefaultConfig;
|
||||||
|
}
|
||||||
|
|
||||||
private void PatchAdapterIDs(ref WINDOWS_DISPLAY_CONFIG savedDisplayConfig, Dictionary<ulong, string> currentAdapterMap)
|
private void PatchAdapterIDs(ref WINDOWS_DISPLAY_CONFIG savedDisplayConfig, Dictionary<ulong, string> currentAdapterMap)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -389,10 +410,55 @@ namespace DisplayMagicianShared.Windows
|
|||||||
hdrInfoCount++;
|
hdrInfoCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the list of all display adapters in this machine through GDI
|
||||||
|
Dictionary<string, GDI_DISPLAY_SETTING> gdiDeviceSettings = new Dictionary<string, GDI_DISPLAY_SETTING>();
|
||||||
|
UInt32 displayDeviceNum = 0;
|
||||||
|
DISPLAY_DEVICE displayDevice = new DISPLAY_DEVICE();
|
||||||
|
displayDevice.Size = (UInt32)Marshal.SizeOf<DISPLAY_DEVICE>();
|
||||||
|
while (GDIImport.EnumDisplayDevices(null, displayDeviceNum, ref displayDevice, 0))
|
||||||
|
{
|
||||||
|
// Now we try and grab the GDI Device Settings for each display device
|
||||||
|
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Getting the current Display Settings for {displayDevice.DeviceName}");
|
||||||
|
if (displayDevice.StateFlags.HasFlag(DISPLAY_DEVICE_STATE_FLAGS.AttachedToDesktop) || displayDevice.StateFlags.HasFlag(DISPLAY_DEVICE_STATE_FLAGS.MultiDriver))
|
||||||
|
{
|
||||||
|
// If the display device is attached to the Desktop, or a type of display that is represented by a psudeo mirroring application, then skip this display
|
||||||
|
// e.g. some sort of software interfaced display that doesn't have a physical plug, or maybe uses USB for communication
|
||||||
|
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Getting the current Display Settings for {displayDevice.DeviceName}");
|
||||||
|
DEVICE_MODE currentMode = new DEVICE_MODE();
|
||||||
|
currentMode.Size = (UInt16)Marshal.SizeOf<DEVICE_MODE>();
|
||||||
|
bool gdiWorked = GDIImport.EnumDisplaySettings(displayDevice.DeviceName, DISPLAY_SETTINGS_MODE.CurrentSettings, ref currentMode);
|
||||||
|
if (gdiWorked)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Got the current Display Settings from display {displayDevice.DeviceName}.");
|
||||||
|
GDI_DISPLAY_SETTING myDisplaySetting = new GDI_DISPLAY_SETTING();
|
||||||
|
myDisplaySetting.IsEnabled = true; // Always true if we get here
|
||||||
|
myDisplaySetting.Device = displayDevice;
|
||||||
|
myDisplaySetting.DeviceMode = currentMode;
|
||||||
|
if (displayDevice.StateFlags.HasFlag(DISPLAY_DEVICE_STATE_FLAGS.PrimaryDevice))
|
||||||
|
{
|
||||||
|
// This is a primary device, so we'll set that too.
|
||||||
|
myDisplaySetting.IsPrimary = true;
|
||||||
|
}
|
||||||
|
gdiDeviceSettings[displayDevice.DeviceName] = myDisplaySetting;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"WinLibrary/GetWindowsDisplayConfig: WARNING - Unabled to get current display mode settings from display {displayDevice.DeviceName}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: The display {displayDevice.DeviceName} is either not attached to the desktop, or is not a mirroring driver. Skipping this display device as we cannot use it.");
|
||||||
|
}
|
||||||
|
|
||||||
|
displayDeviceNum++;
|
||||||
|
}
|
||||||
|
|
||||||
// Store the active paths and modes in our display config object
|
// Store the active paths and modes in our display config object
|
||||||
windowsDisplayConfig.DisplayConfigPaths = paths;
|
windowsDisplayConfig.DisplayConfigPaths = paths;
|
||||||
windowsDisplayConfig.DisplayConfigModes = modes;
|
windowsDisplayConfig.DisplayConfigModes = modes;
|
||||||
windowsDisplayConfig.DisplayHDRStates = hdrInfos;
|
windowsDisplayConfig.DisplayHDRStates = hdrInfos;
|
||||||
|
windowsDisplayConfig.GdiDisplaySettings = gdiDeviceSettings;
|
||||||
windowsDisplayConfig.DisplayIdentifiers = GetCurrentDisplayIdentifiers();
|
windowsDisplayConfig.DisplayIdentifiers = GetCurrentDisplayIdentifiers();
|
||||||
|
|
||||||
return windowsDisplayConfig;
|
return windowsDisplayConfig;
|
||||||
@ -620,6 +686,8 @@ namespace DisplayMagicianShared.Windows
|
|||||||
SharedLogger.logger.Warn($"WinLibrary/GetWindowsDisplayConfig: WARNING - DisplayConfigGetDeviceInfo returned WIN32STATUS {err} when trying to get the adapter device path for target #{path.TargetInfo.AdapterId}");
|
SharedLogger.logger.Warn($"WinLibrary/GetWindowsDisplayConfig: WARNING - DisplayConfigGetDeviceInfo returned WIN32STATUS {err} when trying to get the adapter device path for target #{path.TargetInfo.AdapterId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// show the
|
||||||
|
|
||||||
// get display target preferred mode
|
// get display target preferred mode
|
||||||
var targetPreferredInfo = new DISPLAYCONFIG_TARGET_PREFERRED_MODE();
|
var targetPreferredInfo = new DISPLAYCONFIG_TARGET_PREFERRED_MODE();
|
||||||
targetPreferredInfo.Header.Type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE;
|
targetPreferredInfo.Header.Type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE;
|
||||||
@ -745,6 +813,76 @@ namespace DisplayMagicianShared.Windows
|
|||||||
SharedLogger.logger.Warn($"WinLibrary/GetWindowsDisplayConfig: WARNING - DisplayConfigGetDeviceInfo returned WIN32STATUS {err} when trying to find out the SDL white level for display #{path.TargetInfo.Id}");
|
SharedLogger.logger.Warn($"WinLibrary/GetWindowsDisplayConfig: WARNING - DisplayConfigGetDeviceInfo returned WIN32STATUS {err} when trying to find out the SDL white level for display #{path.TargetInfo.Id}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the list of all display adapters in this machine through GDI
|
||||||
|
Dictionary<string, GDI_DISPLAY_SETTING> gdiDeviceSettings = new Dictionary<string, GDI_DISPLAY_SETTING>();
|
||||||
|
UInt32 displayDeviceNum = 0;
|
||||||
|
DISPLAY_DEVICE displayDevice = new DISPLAY_DEVICE();
|
||||||
|
displayDevice.Size = (UInt32)Marshal.SizeOf<DISPLAY_DEVICE>();
|
||||||
|
stringToReturn += $"----++++==== GDI Device Information ====++++----\n";
|
||||||
|
while (GDIImport.EnumDisplayDevices(null, displayDeviceNum, ref displayDevice, 0))
|
||||||
|
{
|
||||||
|
// Now we try and grab the GDI Device Info for each display device
|
||||||
|
stringToReturn += $"****** Display Device Info for Display {displayDevice.DeviceName} *******\n";
|
||||||
|
stringToReturn += $" Display Device ID: {displayDevice.DeviceId}\n";
|
||||||
|
stringToReturn += $" Display Device Key: {displayDevice.DeviceKey}\n";
|
||||||
|
stringToReturn += $" Display Device Name: {displayDevice.DeviceName}\n";
|
||||||
|
stringToReturn += $" Display Device String: {displayDevice.DeviceString}\n";
|
||||||
|
stringToReturn += $" Is Attached to Desktop: {displayDevice.StateFlags.HasFlag(DISPLAY_DEVICE_STATE_FLAGS.AttachedToDesktop)}\n";
|
||||||
|
stringToReturn += $" Is Disconnected: {displayDevice.StateFlags.HasFlag(DISPLAY_DEVICE_STATE_FLAGS.Disconnect)}\n";
|
||||||
|
stringToReturn += $" Is a Mirroing Device: {displayDevice.StateFlags.HasFlag(DISPLAY_DEVICE_STATE_FLAGS.MirroringDriver)}\n";
|
||||||
|
stringToReturn += $" Has Modes Pruned: {displayDevice.StateFlags.HasFlag(DISPLAY_DEVICE_STATE_FLAGS.ModesPruned)}\n";
|
||||||
|
stringToReturn += $" Is Multi-driver: {displayDevice.StateFlags.HasFlag(DISPLAY_DEVICE_STATE_FLAGS.MultiDriver)}\n";
|
||||||
|
stringToReturn += $" Is Primary Display Device: {displayDevice.StateFlags.HasFlag(DISPLAY_DEVICE_STATE_FLAGS.PrimaryDevice)}\n";
|
||||||
|
stringToReturn += $" Is Remote Display Device: {displayDevice.StateFlags.HasFlag(DISPLAY_DEVICE_STATE_FLAGS.Remote)}\n";
|
||||||
|
stringToReturn += $" Is Removable Display Device: {displayDevice.StateFlags.HasFlag(DISPLAY_DEVICE_STATE_FLAGS.Removable)}\n";
|
||||||
|
stringToReturn += $" Is VGA Compatible Display Device: {displayDevice.StateFlags.HasFlag(DISPLAY_DEVICE_STATE_FLAGS.VGACompatible)}\n";
|
||||||
|
stringToReturn += $"\n";
|
||||||
|
|
||||||
|
|
||||||
|
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Getting the current Display Settings for {displayDevice.DeviceName}");
|
||||||
|
if (displayDevice.StateFlags.HasFlag(DISPLAY_DEVICE_STATE_FLAGS.AttachedToDesktop) || displayDevice.StateFlags.HasFlag(DISPLAY_DEVICE_STATE_FLAGS.MultiDriver))
|
||||||
|
{
|
||||||
|
// If the display device is attached to the Desktop, or a type of display that is represented by a psudeo mirroring application, then skip this display
|
||||||
|
// e.g. some sort of software interfaced display that doesn't have a physical plug, or maybe uses USB for communication
|
||||||
|
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Getting the current Display Settings for {displayDevice.DeviceName}");
|
||||||
|
stringToReturn += $" Display Device Settings for attached Display {displayDevice.DeviceName} :\n";
|
||||||
|
DEVICE_MODE currentMode = new DEVICE_MODE();
|
||||||
|
currentMode.Size = (UInt16)Marshal.SizeOf<DEVICE_MODE>();
|
||||||
|
bool gdiWorked = GDIImport.EnumDisplaySettings(displayDevice.DeviceName, DISPLAY_SETTINGS_MODE.CurrentSettings, ref currentMode);
|
||||||
|
if (gdiWorked)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Got the current Display Settings from display {displayDevice.DeviceName}.");
|
||||||
|
// Now we try and grab the GDI Device Settings for each display device
|
||||||
|
stringToReturn += $" Bits Per Pixel: {currentMode.BitsPerPixel}\n";
|
||||||
|
stringToReturn += $" Device Name: {currentMode.DeviceName}\n";
|
||||||
|
stringToReturn += $" Display Fixed Output: {currentMode.DisplayFixedOutput}\n";
|
||||||
|
stringToReturn += $" Grayscale Display: {currentMode.DisplayFlags.HasFlag(DISPLAY_FLAGS.Grayscale)}\n";
|
||||||
|
stringToReturn += $" Interlaced Display: {currentMode.DisplayFlags.HasFlag(DISPLAY_FLAGS.Interlaced)}\n";
|
||||||
|
stringToReturn += $" Refresh Rate: {currentMode.DisplayFrequency}Hz\n";
|
||||||
|
stringToReturn += $" Display Rotation: {currentMode.DisplayOrientation.ToString("G")}\n";
|
||||||
|
stringToReturn += $" Driver Extra: {currentMode.DriverExtra}\n";
|
||||||
|
stringToReturn += $" Driver Version: {currentMode.DriverVersion}\n";
|
||||||
|
stringToReturn += $" All Display Fields populated by driver: {currentMode.Fields.HasFlag(DEVICE_MODE_FIELDS.AllDisplay)}\n";
|
||||||
|
stringToReturn += $" Display Width and Height in Pixels: {currentMode.PixelsWidth} x {currentMode.PixelsHeight}\n";
|
||||||
|
stringToReturn += $" Display Position: X:{currentMode.Position.X}, Y:{currentMode.Position.Y}\n";
|
||||||
|
stringToReturn += $" Specification Version: {currentMode.SpecificationVersion}\n";
|
||||||
|
stringToReturn += $"\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn($"WinLibrary/GetWindowsDisplayConfig: WARNING - Unabled to get current display mode settings from display {displayDevice.DeviceName}.");
|
||||||
|
stringToReturn += $" No display settings found.\n\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: The display {displayDevice.DeviceName} is either not attached to the desktop, or is not a mirroring driver. Skipping this display device as we cannot use it.");
|
||||||
|
}
|
||||||
|
|
||||||
|
displayDeviceNum++;
|
||||||
|
}
|
||||||
|
|
||||||
return stringToReturn;
|
return stringToReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -793,7 +931,7 @@ namespace DisplayMagicianShared.Windows
|
|||||||
|
|
||||||
foreach (ADVANCED_HDR_INFO_PER_PATH myHDRstate in displayConfig.DisplayHDRStates)
|
foreach (ADVANCED_HDR_INFO_PER_PATH myHDRstate in displayConfig.DisplayHDRStates)
|
||||||
{
|
{
|
||||||
SharedLogger.logger.Trace($"Trying to get information whether HDR color is in use now on Display {myHDRstate.Id}.");
|
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Trying to get information whether HDR color is in use now on Display {myHDRstate.Id}.");
|
||||||
// Get advanced HDR info
|
// Get advanced HDR info
|
||||||
var colorInfo = new DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO();
|
var colorInfo = new DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO();
|
||||||
colorInfo.Header.Type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO;
|
colorInfo.Header.Type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO;
|
||||||
@ -807,7 +945,7 @@ namespace DisplayMagicianShared.Windows
|
|||||||
|
|
||||||
if (myHDRstate.AdvancedColorInfo.AdvancedColorSupported && colorInfo.AdvancedColorEnabled != myHDRstate.AdvancedColorInfo.AdvancedColorEnabled)
|
if (myHDRstate.AdvancedColorInfo.AdvancedColorSupported && colorInfo.AdvancedColorEnabled != myHDRstate.AdvancedColorInfo.AdvancedColorEnabled)
|
||||||
{
|
{
|
||||||
SharedLogger.logger.Trace($"HDR is available for use on Display {myHDRstate.Id}, and we want it set to {myHDRstate.AdvancedColorInfo.AdvancedColorEnabled} but is currently {colorInfo.AdvancedColorEnabled}.");
|
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: HDR is available for use on Display {myHDRstate.Id}, and we want it set to {myHDRstate.AdvancedColorInfo.AdvancedColorEnabled} but is currently {colorInfo.AdvancedColorEnabled}.");
|
||||||
|
|
||||||
var setColorState = new DISPLAYCONFIG_SET_ADVANCED_COLOR_STATE();
|
var setColorState = new DISPLAYCONFIG_SET_ADVANCED_COLOR_STATE();
|
||||||
setColorState.Header.Type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_SET_ADVANCED_COLOR_STATE;
|
setColorState.Header.Type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_SET_ADVANCED_COLOR_STATE;
|
||||||
@ -836,6 +974,61 @@ namespace DisplayMagicianShared.Windows
|
|||||||
SharedLogger.logger.Warn($"WinLibrary/GetWindowsDisplayConfig: WARNING - DisplayConfigGetDeviceInfo returned WIN32STATUS {err} when trying to find out if HDR is supported for display #{myHDRstate.Id}");
|
SharedLogger.logger.Warn($"WinLibrary/GetWindowsDisplayConfig: WARNING - DisplayConfigGetDeviceInfo returned WIN32STATUS {err} when trying to find out if HDR is supported for display #{myHDRstate.Id}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to set the display adapters in this machine through GDI
|
||||||
|
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Attempting to change Display Device settings through GDI API");
|
||||||
|
foreach (var myGdiDisplaySettings in displayConfig.GdiDisplaySettings)
|
||||||
|
{
|
||||||
|
string displayDeviceName = myGdiDisplaySettings.Key;
|
||||||
|
GDI_DISPLAY_SETTING displayDeviceSettings = myGdiDisplaySettings.Value;
|
||||||
|
SharedLogger.logger.Trace($"WinLibrary/SetActiveConfig: Trying to change Device Mode for Display {displayDeviceName}.");
|
||||||
|
DEVICE_MODE modeToUse = displayDeviceSettings.DeviceMode;
|
||||||
|
CHANGE_DISPLAY_RESULTS result = GDIImport.ChangeDisplaySettingsEx(displayDeviceName, ref modeToUse, IntPtr.Zero, CHANGE_DISPLAY_SETTINGS_FLAGS.CDS_UPDATEREGISTRY, IntPtr.Zero);
|
||||||
|
if (result == CHANGE_DISPLAY_RESULTS.Successful)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Successfully changed display {displayDeviceName} to use the new mode!");
|
||||||
|
}
|
||||||
|
else if (result == CHANGE_DISPLAY_RESULTS.BadDualView)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"WinLibrary/GetWindowsDisplayConfig: The settings change was unsuccessful because the system is DualView capable. Display {displayDeviceName} not updated to new mode.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (result == CHANGE_DISPLAY_RESULTS.BadFlags)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"WinLibrary/GetWindowsDisplayConfig: An invalid set of flags was passed in. Display {displayDeviceName} not updated to use the new mode.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (result == CHANGE_DISPLAY_RESULTS.BadMode)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"WinLibrary/GetWindowsDisplayConfig: The graphics mode is not supported. Display {displayDeviceName} not updated to use the new mode.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (result == CHANGE_DISPLAY_RESULTS.BadParam)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"WinLibrary/GetWindowsDisplayConfig: An invalid parameter was passed in. This can include an invalid flag or combination of flags. Display {displayDeviceName} not updated to use the new mode.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (result == CHANGE_DISPLAY_RESULTS.Failed)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"WinLibrary/GetWindowsDisplayConfig: The display driver failed to apply the specified graphics mode. Display {displayDeviceName} not updated to use the new mode.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (result == CHANGE_DISPLAY_RESULTS.NotUpdated)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"WinLibrary/GetWindowsDisplayConfig: Unable to write new settings to the registry. Display {displayDeviceName} not updated to use the new mode.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (result == CHANGE_DISPLAY_RESULTS.Restart)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Error($"WinLibrary/GetWindowsDisplayConfig: The computer must be restarted for the graphics mode to work. Display {displayDeviceName} not updated to use the new mode.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Display {displayDeviceName} not updated to use the new mode.");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user