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:
@ -7,6 +7,7 @@ using Microsoft.Win32.SafeHandles;
|
||||
using DisplayMagicianShared;
|
||||
using System.ComponentModel;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DisplayMagicianShared.Windows
|
||||
{
|
||||
@ -41,6 +42,7 @@ namespace DisplayMagicianShared.Windows
|
||||
public DISPLAYCONFIG_PATH_INFO[] DisplayConfigPaths;
|
||||
public DISPLAYCONFIG_MODE_INFO[] DisplayConfigModes;
|
||||
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
|
||||
// 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.
|
||||
@ -52,11 +54,12 @@ namespace DisplayMagicianShared.Windows
|
||||
=> DisplayConfigPaths.SequenceEqual(other.DisplayConfigPaths) &&
|
||||
DisplayConfigModes.SequenceEqual(other.DisplayConfigModes) &&
|
||||
DisplayHDRStates.SequenceEqual(other.DisplayHDRStates) &&
|
||||
GdiDisplaySettings.SequenceEqual(other.GdiDisplaySettings) &&
|
||||
DisplayIdentifiers.SequenceEqual(other.DisplayIdentifiers);
|
||||
|
||||
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);
|
||||
|
||||
@ -128,6 +131,24 @@ namespace DisplayMagicianShared.Windows
|
||||
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)
|
||||
{
|
||||
|
||||
@ -389,10 +410,55 @@ namespace DisplayMagicianShared.Windows
|
||||
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
|
||||
windowsDisplayConfig.DisplayConfigPaths = paths;
|
||||
windowsDisplayConfig.DisplayConfigModes = modes;
|
||||
windowsDisplayConfig.DisplayHDRStates = hdrInfos;
|
||||
windowsDisplayConfig.GdiDisplaySettings = gdiDeviceSettings;
|
||||
windowsDisplayConfig.DisplayIdentifiers = GetCurrentDisplayIdentifiers();
|
||||
|
||||
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}");
|
||||
}
|
||||
|
||||
// show the
|
||||
|
||||
// get display target preferred mode
|
||||
var targetPreferredInfo = new DISPLAYCONFIG_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}");
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@ -793,7 +931,7 @@ namespace DisplayMagicianShared.Windows
|
||||
|
||||
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
|
||||
var colorInfo = new DISPLAYCONFIG_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)
|
||||
{
|
||||
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();
|
||||
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}");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user