diff --git a/ColorControl/ColorControl.csproj b/ColorControl/ColorControl.csproj index b449bd4..6b56110 100644 --- a/ColorControl/ColorControl.csproj +++ b/ColorControl/ColorControl.csproj @@ -18,8 +18,8 @@ Maassoft Maassoft 0 - 9.9.0.0 - 9.9.0.0 + 9.9.0.1 + 9.9.0.1 false true false diff --git a/ColorControl/Forms/OptionsPanel.cs b/ColorControl/Forms/OptionsPanel.cs index afd036f..b6524cb 100644 --- a/ColorControl/Forms/OptionsPanel.cs +++ b/ColorControl/Forms/OptionsPanel.cs @@ -311,8 +311,15 @@ Currently ColorControl is {(_winApiService.IsAdministrator() ? "" : "not ")}runn SubLabel = "When this is enabled MinTML and MaxTML will be automatically be set to respectively the minimum luminance and the maximum luminance of the color profile", Value = _config.SetMinTmlAndMaxTml }; + var disableErrorPopupField = new FieldDefinition + { + FieldType = FieldType.CheckBox, + Label = "Disable error popup when applying presets", + SubLabel = "Check this to disable the error popup when there was an error applying a preset", + Value = _config.DisableErrorPopupWhenApplyingPreset + }; - var values = MessageForms.ShowDialog("Advanced settings", new[] { processPollingIntervalField, useRawInputField, setMinTmlAndMaxTmlField }); + var values = MessageForms.ShowDialog("Advanced settings", new[] { processPollingIntervalField, useRawInputField, setMinTmlAndMaxTmlField, disableErrorPopupField }); if (values?.Any() != true) { @@ -322,6 +329,7 @@ Currently ColorControl is {(_winApiService.IsAdministrator() ? "" : "not ")}runn _config.ProcessMonitorPollingInterval = processPollingIntervalField.ValueAsInt; _config.UseRawInput = useRawInputField.ValueAsBool; _config.SetMinTmlAndMaxTml = setMinTmlAndMaxTmlField.ValueAsBool; + _config.DisableErrorPopupWhenApplyingPreset = disableErrorPopupField.ValueAsBool; _keyboardShortcutDispatcher.SetUseRawInput(_config.UseRawInput); } diff --git a/ColorControl/MainForm.cs b/ColorControl/MainForm.cs index c656b04..b66d72f 100644 --- a/ColorControl/MainForm.cs +++ b/ColorControl/MainForm.cs @@ -37,6 +37,7 @@ namespace ColorControl public NotifyIconManager _notifyIconManager; private readonly KeyboardShortcutDispatcher _keyboardShortcutDispatcher; private readonly UpdateManager _updateManager; + private readonly WindowMessageDispatcher _windowMessageDispatcher; private Config _config; private LgPanel _lgPanel; @@ -48,7 +49,7 @@ namespace ColorControl private GamePanel _gamePanel; public MainForm(GlobalContext globalContext, ServiceManager serviceManager, IServiceProvider serviceProvider, ElevationService elevationService, - NotifyIconManager notifyIconManager, KeyboardShortcutDispatcher keyboardShortcutDispatcher, UpdateManager updateManager) + NotifyIconManager notifyIconManager, KeyboardShortcutDispatcher keyboardShortcutDispatcher, UpdateManager updateManager, WindowMessageDispatcher windowMessageDispatcher) { InitializeComponent(); @@ -60,6 +61,7 @@ namespace ColorControl _notifyIconManager = notifyIconManager; _keyboardShortcutDispatcher = keyboardShortcutDispatcher; _updateManager = updateManager; + _windowMessageDispatcher = windowMessageDispatcher; _config = Program.Config; Text = globalContext.ApplicationTitleAdmin; @@ -178,10 +180,8 @@ namespace ColorControl if (m.Msg == NativeConstants.WM_QUERYENDSESSION) { SystemShutdown = true; - } - else if (m.Msg == NativeConstants.WM_ENDSESSION) - { EndSession = true; + _windowMessageDispatcher.DispatchEvent(WindowMessageDispatcher.Event_WindowMessageQueryEndSession, new WindowMessageEventArgs(m)); } else if (m.Msg == Utils.WM_BRINGTOFRONT) { diff --git a/ColorControl/MainWorker.cs b/ColorControl/MainWorker.cs index 9ddbfef..5fdb5d6 100644 --- a/ColorControl/MainWorker.cs +++ b/ColorControl/MainWorker.cs @@ -30,7 +30,6 @@ internal class MainWorker private readonly WinApiService _winApiService; private readonly WinApiAdminService _winApiAdminService; private readonly UpdateManager _updateManager; - private bool _queryEndSession; private nint _screenStateNotify; public static int SHORTCUTID_SCREENSAVER = -100; @@ -85,7 +84,6 @@ internal class MainWorker _globalContext.SynchronizationContext = AsyncOperationManager.SynchronizationContext; _windowMessageDispatcher.RegisterEventHandler(WindowMessageDispatcher.Event_WindowMessageQueryEndSession, HandleQueryEndSessionEvent); - _windowMessageDispatcher.RegisterEventHandler(WindowMessageDispatcher.Event_WindowMessageClose, HandleCloseEvent); _windowMessageDispatcher.RegisterEventHandler(WindowMessageDispatcher.Event_WindowMessagePowerBroadcast, HandlePowerBroadcastEvent); _windowMessageDispatcher.RegisterEventHandler(WindowMessageDispatcher.Event_WindowMessageShowWindow, HandleShowWindowEvent); _windowMessageDispatcher.RegisterEventHandler(WindowMessageDispatcher.Event_WindowMessageUserBringToFront, HandleUserBringToFrontEvent); @@ -151,21 +149,12 @@ internal class MainWorker } } - private void HandleCloseEvent(object sender, WindowMessageEventArgs e) - { - if (_queryEndSession) - { - Logger.Debug($"MainWorker: SystemShutdown"); - - _powerEventDispatcher.SendEvent(PowerEventDispatcher.Event_Shutdown); - } - } - private void HandleQueryEndSessionEvent(object sender, WindowMessageEventArgs e) { - Logger.Debug("MainWorker: QueryEndSession"); + Logger.Debug($"MainWorker: QueryEndSession"); + Logger.Debug($"MainWorker: SystemShutdown"); - _queryEndSession = true; + _powerEventDispatcher.SendEvent(PowerEventDispatcher.Event_Shutdown); } private void HandleHotKeyEvent(object sender, KeyboardShortcutEventArgs args) diff --git a/ColorControl/Services/AMD/AmdPanel.cs b/ColorControl/Services/AMD/AmdPanel.cs index 6d45b69..97613e5 100644 --- a/ColorControl/Services/AMD/AmdPanel.cs +++ b/ColorControl/Services/AMD/AmdPanel.cs @@ -92,7 +92,7 @@ namespace ColorControl.Services.AMD item = lvAmdPresets.Items.Add(display.DisplayName); item.ImageIndex = id; item.Font = new Font(item.Font, item.Font.Style | FontStyle.Bold); - item.BackColor = Color.LightGray; + item.BackColor = _globalContext.Config.UseDarkMode ? DarkModeUtils.ListViewDarkModeBackColor : Color.LightGray; } var values = displayInfo.Values; diff --git a/ColorControl/Services/AMD/AmdPreset.cs b/ColorControl/Services/AMD/AmdPreset.cs index 3fcb149..4fc9da0 100644 --- a/ColorControl/Services/AMD/AmdPreset.cs +++ b/ColorControl/Services/AMD/AmdPreset.cs @@ -65,9 +65,10 @@ namespace ColorControl.Services.AMD public override List GetDisplayValues(Config config = null) { - var values = new List(); - - values.Add(name); + var values = new List + { + name + }; var display = string.Format("{0}", primaryDisplay ? "Primary" : displayName); values.Add(display); diff --git a/ColorControl/Services/AMD/AmdService.cs b/ColorControl/Services/AMD/AmdService.cs index 5be9967..2c6debc 100644 --- a/ColorControl/Services/AMD/AmdService.cs +++ b/ColorControl/Services/AMD/AmdService.cs @@ -305,10 +305,11 @@ namespace ColorControl.Services.AMD var index = 0; foreach (var screen in Screen.AllScreens) { - Logger.Debug($"SCREEN[{index}]: {screen.DeviceName}, {screen.DeviceFriendlyName()}, {screen.Primary}"); + var info = CCD.GetDisplayInfo(screen.DeviceName); + Logger.Debug($"SCREEN[{index}]: {screen.DeviceName}, {info?.FriendlyName}, {screen.Primary}"); index++; } - return Screen.AllScreens.FirstOrDefault(x => x.DeviceFriendlyName().Equals(display.DisplayName)); + return Screen.AllScreens.FirstOrDefault(x => CCD.GetDisplayInfo(x.DeviceName)?.FriendlyName.Equals(display.DisplayName) ?? false); } public List GetDisplayInfos() @@ -328,9 +329,10 @@ namespace ColorControl.Services.AMD foreach (var display in displays) { - var values = new List(); - - values.Add("Current settings"); + var values = new List + { + "Current settings" + }; var screen = GetScreenForDisplay(display); diff --git a/ColorControl/Services/Common/ServiceBase.cs b/ColorControl/Services/Common/ServiceBase.cs index 035b782..51c9ac7 100644 --- a/ColorControl/Services/Common/ServiceBase.cs +++ b/ColorControl/Services/Common/ServiceBase.cs @@ -93,7 +93,10 @@ namespace ColorControl.Services.Common { Logger.Error(e); - MessageForms.ErrorOk($"Error applying {ServiceName}-preset ({e.TargetSite.Name}): {e.Message}"); + if (!_globalContext.Config.DisableErrorPopupWhenApplyingPreset) + { + MessageForms.ErrorOk($"Error applying {ServiceName}-preset ({preset.IdOrName}): {e.Message}"); + } return false; } } diff --git a/ColorControl/Services/NVIDIA/NvDisplayInfo.cs b/ColorControl/Services/NVIDIA/NvDisplayInfo.cs index c37a541..cca371d 100644 --- a/ColorControl/Services/NVIDIA/NvDisplayInfo.cs +++ b/ColorControl/Services/NVIDIA/NvDisplayInfo.cs @@ -1,4 +1,6 @@ -using NvAPIWrapper.Display; +using ColorControl.Shared.Native; +using NStandard; +using NvAPIWrapper.Display; using System.Collections.Generic; namespace ColorControl.Services.NVIDIA @@ -7,18 +9,52 @@ namespace ColorControl.Services.NVIDIA { public Display Display { get; } - public List Values { get; } + public List Values { get; set; } - public string InfoLine { get; } + public string InfoLine { get; set; } - public string Name { get; } + public string Name { get; private set; } - public NvDisplayInfo(Display display, List values, string infoLine, string name) + public string DisplayId { get; private set; } + + public NvDisplayInfo(Display display, List values, string infoLine, string name = null) { Display = display; Values = values; InfoLine = infoLine; Name = name; + + SetDisplayName(); + } + + private void SetDisplayName() + { + if (!Name.IsNullOrEmpty()) + { + return; + } + + + if (Display == null) + { + Name = "Unknown"; + + return; + } + + var info = CCD.GetDisplayInfo(Display.Name); + + Name = info?.FriendlyName; + DisplayId = info?.DisplayId; + + if (Name.IsNullOrEmpty()) + { + Name = DisplayId; + } + else + { + Name = $"{Name} ({DisplayId})"; + } } public override string ToString() diff --git a/ColorControl/Services/NVIDIA/NvPanel.Designer.cs b/ColorControl/Services/NVIDIA/NvPanel.Designer.cs index 416f490..11a30cd 100644 --- a/ColorControl/Services/NVIDIA/NvPanel.Designer.cs +++ b/ColorControl/Services/NVIDIA/NvPanel.Designer.cs @@ -61,6 +61,10 @@ namespace ColorControl.Services.NVIDIA miNvPresetColorEnhancementsIncluded = new System.Windows.Forms.ToolStripMenuItem(); mnuRefreshRate = new System.Windows.Forms.ToolStripMenuItem(); miRefreshRateIncluded = new System.Windows.Forms.ToolStripMenuItem(); + mnuNvResolution = new System.Windows.Forms.ToolStripMenuItem(); + miNvResolutionIncluded = new System.Windows.Forms.ToolStripMenuItem(); + mnuNvActiveResolution = new System.Windows.Forms.ToolStripMenuItem(); + mnuNvVirtualResolution = new System.Windows.Forms.ToolStripMenuItem(); miNvPresetDithering = new System.Windows.Forms.ToolStripMenuItem(); miNvPresetApplyDithering = new System.Windows.Forms.ToolStripMenuItem(); miNvPresetDitheringEnabled = new System.Windows.Forms.ToolStripMenuItem(); @@ -102,10 +106,6 @@ namespace ColorControl.Services.NVIDIA miNvTestDithering = new System.Windows.Forms.ToolStripMenuItem(); miNVIDIAInfo = new System.Windows.Forms.ToolStripMenuItem(); lvNvPresetsToolTip = new System.Windows.Forms.ToolTip(components); - mnuNvResolution = new System.Windows.Forms.ToolStripMenuItem(); - miNvResolutionIncluded = new System.Windows.Forms.ToolStripMenuItem(); - mnuNvActiveResolution = new System.Windows.Forms.ToolStripMenuItem(); - mnuNvVirtualResolution = new System.Windows.Forms.ToolStripMenuItem(); mnuNvPresets.SuspendLayout(); mnuNvSettings.SuspendLayout(); SuspendLayout(); @@ -385,7 +385,7 @@ namespace ColorControl.Services.NVIDIA // miNvPresetColorSettings // miNvPresetColorSettings.Name = "miNvPresetColorSettings"; - miNvPresetColorSettings.Size = new System.Drawing.Size(180, 22); + miNvPresetColorSettings.Size = new System.Drawing.Size(120, 22); miNvPresetColorSettings.Text = "Included"; miNvPresetColorSettings.Click += miNvPresetColorSettings_Click; // @@ -399,7 +399,7 @@ namespace ColorControl.Services.NVIDIA // miNvPresetColorEnhancementsIncluded // miNvPresetColorEnhancementsIncluded.Name = "miNvPresetColorEnhancementsIncluded"; - miNvPresetColorEnhancementsIncluded.Size = new System.Drawing.Size(180, 22); + miNvPresetColorEnhancementsIncluded.Size = new System.Drawing.Size(120, 22); miNvPresetColorEnhancementsIncluded.Text = "Included"; miNvPresetColorEnhancementsIncluded.Click += miNvPresetColorEnhancementsIncluded_Click; // @@ -409,14 +409,42 @@ namespace ColorControl.Services.NVIDIA mnuRefreshRate.Name = "mnuRefreshRate"; mnuRefreshRate.Size = new System.Drawing.Size(184, 22); mnuRefreshRate.Text = "Refresh Rate"; + mnuRefreshRate.DropDownOpening += mnuRefreshRate_DropDownOpening; // // miRefreshRateIncluded // miRefreshRateIncluded.Name = "miRefreshRateIncluded"; - miRefreshRateIncluded.Size = new System.Drawing.Size(180, 22); + miRefreshRateIncluded.Size = new System.Drawing.Size(120, 22); miRefreshRateIncluded.Text = "Included"; miRefreshRateIncluded.Click += includedToolStripMenuItem_Click; // + // mnuNvResolution + // + mnuNvResolution.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { miNvResolutionIncluded, mnuNvActiveResolution, mnuNvVirtualResolution }); + mnuNvResolution.Name = "mnuNvResolution"; + mnuNvResolution.Size = new System.Drawing.Size(184, 22); + mnuNvResolution.Text = "Resolution"; + mnuNvResolution.DropDownOpening += mnuNvResolution_DropDownOpening; + // + // miNvResolutionIncluded + // + miNvResolutionIncluded.Name = "miNvResolutionIncluded"; + miNvResolutionIncluded.Size = new System.Drawing.Size(180, 22); + miNvResolutionIncluded.Text = "Included"; + miNvResolutionIncluded.Click += miNvResolutionIncluded_Click; + // + // mnuNvActiveResolution + // + mnuNvActiveResolution.Name = "mnuNvActiveResolution"; + mnuNvActiveResolution.Size = new System.Drawing.Size(180, 22); + mnuNvActiveResolution.Text = "Active"; + // + // mnuNvVirtualResolution + // + mnuNvVirtualResolution.Name = "mnuNvVirtualResolution"; + mnuNvVirtualResolution.Size = new System.Drawing.Size(180, 22); + mnuNvVirtualResolution.Text = "Virtual"; + // // miNvPresetDithering // miNvPresetDithering.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { miNvPresetApplyDithering, miNvPresetDitheringEnabled, mnuNvDitheringBitDepth, mnuNvDitheringMode }); @@ -427,14 +455,14 @@ namespace ColorControl.Services.NVIDIA // miNvPresetApplyDithering // miNvPresetApplyDithering.Name = "miNvPresetApplyDithering"; - miNvPresetApplyDithering.Size = new System.Drawing.Size(180, 22); + miNvPresetApplyDithering.Size = new System.Drawing.Size(122, 22); miNvPresetApplyDithering.Text = "Included"; miNvPresetApplyDithering.Click += miNvPresetApplyDithering_Click; // // miNvPresetDitheringEnabled // miNvPresetDitheringEnabled.Name = "miNvPresetDitheringEnabled"; - miNvPresetDitheringEnabled.Size = new System.Drawing.Size(180, 22); + miNvPresetDitheringEnabled.Size = new System.Drawing.Size(122, 22); miNvPresetDitheringEnabled.Text = "Enabled"; miNvPresetDitheringEnabled.Click += miNvPresetDitheringEnabled_Click; // @@ -442,7 +470,7 @@ namespace ColorControl.Services.NVIDIA // mnuNvDitheringBitDepth.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { miNvDithering6bit, miNvDithering8bit, miNvDithering10bit }); mnuNvDitheringBitDepth.Name = "mnuNvDitheringBitDepth"; - mnuNvDitheringBitDepth.Size = new System.Drawing.Size(180, 22); + mnuNvDitheringBitDepth.Size = new System.Drawing.Size(122, 22); mnuNvDitheringBitDepth.Text = "Bit depth"; // // miNvDithering6bit @@ -473,7 +501,7 @@ namespace ColorControl.Services.NVIDIA // mnuNvDitheringMode.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { spatial1ToolStripMenuItem, spatial2ToolStripMenuItem, spatialDynamic2x2ToolStripMenuItem, spatialStatic2x2ToolStripMenuItem, temporalToolStripMenuItem }); mnuNvDitheringMode.Name = "mnuNvDitheringMode"; - mnuNvDitheringMode.Size = new System.Drawing.Size(180, 22); + mnuNvDitheringMode.Size = new System.Drawing.Size(122, 22); mnuNvDitheringMode.Text = "Mode"; // // spatial1ToolStripMenuItem @@ -584,7 +612,7 @@ namespace ColorControl.Services.NVIDIA // miNvDriverSettingsIncluded // miNvDriverSettingsIncluded.Name = "miNvDriverSettingsIncluded"; - miNvDriverSettingsIncluded.Size = new System.Drawing.Size(180, 22); + miNvDriverSettingsIncluded.Size = new System.Drawing.Size(120, 22); miNvDriverSettingsIncluded.Text = "Included"; miNvDriverSettingsIncluded.Click += miNvDriverSettingsIncluded_Click; // @@ -598,7 +626,7 @@ namespace ColorControl.Services.NVIDIA // miNvOtherIncluded // miNvOtherIncluded.Name = "miNvOtherIncluded"; - miNvOtherIncluded.Size = new System.Drawing.Size(180, 22); + miNvOtherIncluded.Size = new System.Drawing.Size(120, 22); miNvOtherIncluded.Text = "Included"; miNvOtherIncluded.Click += miNvOtherIncluded_Click; // @@ -612,7 +640,7 @@ namespace ColorControl.Services.NVIDIA // miNvHdmiIncluded // miNvHdmiIncluded.Name = "miNvHdmiIncluded"; - miNvHdmiIncluded.Size = new System.Drawing.Size(180, 22); + miNvHdmiIncluded.Size = new System.Drawing.Size(120, 22); miNvHdmiIncluded.Text = "Included"; miNvHdmiIncluded.Click += miNvHdmiIncluded_Click; // @@ -728,32 +756,6 @@ namespace ColorControl.Services.NVIDIA miNVIDIAInfo.Text = "NVIDIA Info"; miNVIDIAInfo.Click += miNVIDIAInfo_Click; // - // mnuNvResolution - // - mnuNvResolution.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { miNvResolutionIncluded, mnuNvActiveResolution, mnuNvVirtualResolution }); - mnuNvResolution.Name = "mnuNvResolution"; - mnuNvResolution.Size = new System.Drawing.Size(184, 22); - mnuNvResolution.Text = "Resolution"; - // - // miNvResolutionIncluded - // - miNvResolutionIncluded.Name = "miNvResolutionIncluded"; - miNvResolutionIncluded.Size = new System.Drawing.Size(180, 22); - miNvResolutionIncluded.Text = "Included"; - miNvResolutionIncluded.Click += miNvResolutionIncluded_Click; - // - // mnuNvActiveResolution - // - mnuNvActiveResolution.Name = "mnuNvActiveResolution"; - mnuNvActiveResolution.Size = new System.Drawing.Size(180, 22); - mnuNvActiveResolution.Text = "Active"; - // - // mnuNvVirtualResolution - // - mnuNvVirtualResolution.Name = "mnuNvVirtualResolution"; - mnuNvVirtualResolution.Size = new System.Drawing.Size(180, 22); - mnuNvVirtualResolution.Text = "Virtual"; - // // NvPanel // AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); diff --git a/ColorControl/Services/NVIDIA/NvPanel.cs b/ColorControl/Services/NVIDIA/NvPanel.cs index f1a6bb4..525a0c2 100644 --- a/ColorControl/Services/NVIDIA/NvPanel.cs +++ b/ColorControl/Services/NVIDIA/NvPanel.cs @@ -34,7 +34,6 @@ namespace ColorControl.Services.NVIDIA private NvService _nvService; private readonly NotifyIconManager _notifyIconManager; private readonly GlobalContext _globalContext; - private string _lastDisplayRefreshRates = string.Empty; private RpcClientService _rpcService; private readonly WinApiAdminService _winApiAdminService; private readonly KeyboardShortcutDispatcher _keyboardShortcutDispatcher; @@ -124,7 +123,7 @@ namespace ColorControl.Services.NVIDIA private void UpdateDisplayInfoItems() { - var displays = _nvService?.GetDisplayInfos(); + var displays = _nvService.GetDisplayInfos(); if (displays == null || Program.IsRestarting) { return; @@ -135,14 +134,12 @@ namespace ColorControl.Services.NVIDIA { var display = displayInfo.Display; - var id = Math.Abs((int)display.Handle.MemoryAddress.ToInt64()); - ListViewItem item = null; for (var i = 0; i < lvNvPresets.Items.Count; i++) { item = lvNvPresets.Items[i]; - if (item.Tag == null && item.ImageIndex == id) + if (item.Tag == null && item.SubItems[1].Text == displayInfo.Name) { break; } @@ -151,12 +148,10 @@ namespace ColorControl.Services.NVIDIA if (item == null) { - item = lvNvPresets.Items.Add(display.Name); - item.ImageIndex = id; + item = lvNvPresets.Items.Add(displayInfo.Name); item.Font = new Font(item.Font, item.Font.Style | FontStyle.Bold); - //item.BackColor = Color.LightGray; } - item.BackColor = _globalContext.Config.UseDarkMode ? Color.DimGray : Color.LightGray; + item.BackColor = _globalContext.Config.UseDarkMode ? DarkModeUtils.ListViewDarkModeBackColor : Color.LightGray; var values = displayInfo.Values; @@ -350,6 +345,7 @@ namespace ColorControl.Services.NVIDIA mnuNvOverclocking.Visible = preset != null && _nvService.Config.ShowOverclocking; mnuNvOtherSettings.Enabled = preset != null; miNvOtherIncluded.Visible = presetItemsVisible; + mnuNvHdmiSettings.Visible = !isCurrentDisplay || preset?.Display?.DisplayDevice.ConnectionType == NvAPIWrapper.Native.GPU.MonitorConnectionType.HDMI; mnuNvHdmiSettings.Enabled = preset != null; miNvHdmiIncluded.Visible = presetItemsVisible; miHDROuputMode.Visible = _nvService.OutputModeAvailable; @@ -370,7 +366,7 @@ namespace ColorControl.Services.NVIDIA miNvPresetColorSettings.Visible = !isCurrentDisplay; miNvPresetColorEnhancementsIncluded.Visible = !isCurrentDisplay; miNvResolutionIncluded.Visible = !isCurrentDisplay; - miRefreshRateIncluded.Visible = !isCurrentDisplay; + miRefreshRateIncluded.Visible = true; // Workaround to make arrow visible miHDRIncluded.Visible = !isCurrentDisplay; miHDROutputModeUnchanged.Visible = !isCurrentDisplay; miHDROutputModeHDR10.Checked = preset.HdrSettings.OutputMode == NvHdrSettings.NV_DISPLAY_OUTPUT_MODE.NV_DISPLAY_OUTPUT_MODE_HDR10; @@ -378,13 +374,10 @@ namespace ColorControl.Services.NVIDIA if (mnuNvDisplay.DropDownItems.Count == 1) { - var displays = _nvService.GetDisplays(); - for (var i = 0; i < displays.Length; i++) + var displays = _nvService.GetDisplayInfos(); + foreach (var display in displays) { - var display = displays[i]; - var name = FormUtils.ExtendedDisplayName(display.Name); - - var item = mnuNvDisplay.DropDownItems.AddCustom(name); + var item = mnuNvDisplay.DropDownItems.AddCustom(display.Name); item.Tag = display; item.Click += displayMenuItem_Click; } @@ -395,14 +388,17 @@ namespace ColorControl.Services.NVIDIA FormUtils.BuildDropDownMenu(mnuNvPresetsColorSettings, "Dynamic range", typeof(ColorDataDynamicRange), preset.colorData, "DynamicRange", nvPresetColorDataMenuItem_Click); FormUtils.BuildDropDownMenu(mnuNvPresetsColorSettings, "Color space", typeof(ColorDataColorimetry), preset.colorData, "Colorimetry", nvPresetColorDataMenuItem_Click); - BuildNvRefreshRateResolutionMenu(preset); + FormUtils.BuildDropDownMenu(mnuNvResolution, "Scaling/Aspect Ratio", typeof(CCD.DisplayConfigScaling), preset.DisplayConfig, "Scaling", UpdateDisplayConfigScaling, unchanged: false, + skipValues: [CCD.DisplayConfigScaling.Zero, CCD.DisplayConfigScaling.Custom, CCD.DisplayConfigScaling.ForceUint32]); + FormUtils.BuildDropDownMenu(mnuNvResolution, "Rotation", typeof(CCD.DisplayConfigRotation), preset.DisplayConfig, "Rotation", UpdateDisplayConfigRotation, unchanged: false, + skipValues: [CCD.DisplayConfigRotation.Zero, CCD.DisplayConfigRotation.ForceUint32]); miNvPrimaryDisplay.Checked = preset.primaryDisplay; foreach (var item in mnuNvDisplay.DropDownItems) { if (item is ToolStripMenuItem menuItem && menuItem.Tag != null) { - menuItem.Checked = ((Display)menuItem.Tag).Name.Equals(preset.displayName); + menuItem.Checked = ((NvDisplayInfo)menuItem.Tag).DisplayId.Equals(preset.DisplayId); } } @@ -509,7 +505,6 @@ namespace ColorControl.Services.NVIDIA return; } - var menuItem = (ToolStripItem)sender; var currentSettings = (NvGpuOcSettings)menuItem.Tag; @@ -528,95 +523,6 @@ namespace ColorControl.Services.NVIDIA AddOrUpdateItem(); } - private void BuildNvRefreshRateResolutionMenu(NvPreset preset) - { - var displayName = preset.primaryDisplay ? null : preset.displayName; - - if (displayName != _lastDisplayRefreshRates) - { - while (mnuRefreshRate.DropDownItems.Count > 1) - { - mnuRefreshRate.DropDownItems.RemoveAt(mnuRefreshRate.DropDownItems.Count - 1); - } - - mnuNvActiveResolution.DropDownItems.Clear(); - mnuNvVirtualResolution.DropDownItems.Clear(); - } - - if (mnuRefreshRate.DropDownItems.Count == 1) - { - var refreshRates = _nvService.GetAvailableRefreshRatesV2(preset); - - _lastDisplayRefreshRates = displayName; - - foreach (var refreshRate in refreshRates) - { - var item = mnuRefreshRate.DropDownItems.AddCustom(refreshRate.ToString() + "Hz"); - item.Tag = refreshRate; - item.Click += refreshRateMenuItem_Click; - } - } - - var modes = default(List); - - if (mnuNvActiveResolution.DropDownItems.Count == 0) - { - modes = _nvService.GetAvailableResolutionsV2(preset); - - foreach (var mode in modes) - { - var item = mnuNvActiveResolution.DropDownItems.AddCustom(mode.ToString()); - item.Tag = mode; - item.Click += resolutionNvMenuItem_Click; - } - } - - if (mnuNvVirtualResolution.DropDownItems.Count == 0) - { - modes ??= _nvService.GetAvailableResolutionsV2(preset); - - foreach (var mode in modes) - { - var item = mnuNvVirtualResolution.DropDownItems.AddCustom(mode.ToString()); - item.Tag = mode; - item.Click += virtualResolutionNvMenuItem_Click; - } - } - - miRefreshRateIncluded.Checked = preset.DisplayConfig.ApplyRefreshRate; - foreach (var item in mnuRefreshRate.DropDownItems) - { - if (item is ToolStripMenuItem menuItem && menuItem.Tag != null) - { - menuItem.Checked = ((Rational)menuItem.Tag).Equals(preset.DisplayConfig.RefreshRate); - } - } - - miNvResolutionIncluded.Checked = preset.DisplayConfig.ApplyResolution; - foreach (var item in mnuNvActiveResolution.DropDownItems) - { - if (item is ToolStripMenuItem menuItem && menuItem.Tag != null) - { - var mode = (VirtualResolution)menuItem.Tag; - menuItem.Checked = mode.ActiveWidth == preset.DisplayConfig.Resolution.ActiveWidth && mode.ActiveHeight == preset.DisplayConfig.Resolution.ActiveHeight; - } - } - - foreach (var item in mnuNvVirtualResolution.DropDownItems) - { - if (item is ToolStripMenuItem menuItem && menuItem.Tag != null) - { - var mode = (VirtualResolution)menuItem.Tag; - menuItem.Checked = mode.VirtualWidth == preset.DisplayConfig.Resolution.VirtualWidth && mode.VirtualHeight == preset.DisplayConfig.Resolution.VirtualHeight; - } - } - - FormUtils.BuildDropDownMenu(mnuNvResolution, "Scaling/Aspect Ratio", typeof(CCD.DisplayConfigScaling), preset.DisplayConfig, "Scaling", UpdateDisplayConfigScaling, unchanged: false, - skipValues: [CCD.DisplayConfigScaling.Zero, CCD.DisplayConfigScaling.Custom, CCD.DisplayConfigScaling.ForceUint32]); - FormUtils.BuildDropDownMenu(mnuNvResolution, "Rotation", typeof(CCD.DisplayConfigRotation), preset.DisplayConfig, "Rotation", UpdateDisplayConfigRotation, unchanged: false, - skipValues: [CCD.DisplayConfigRotation.Zero, CCD.DisplayConfigRotation.ForceUint32]); - } - private void UpdateNvPresetMenuFont(bool updateTopItems = false) { foreach (var menu in mnuNvPresets.Items.OfType().Where(i => i != mnuNvDriverSettings)) @@ -1135,15 +1041,17 @@ namespace ColorControl.Services.NVIDIA var menuItem = (ToolStripItem)sender; if (menuItem.Tag != null) { - var display = (Display)menuItem.Tag; + var displayInfo = (NvDisplayInfo)menuItem.Tag; - preset.displayName = display.Name; + preset.displayName = displayInfo.Name; + preset.DisplayId = displayInfo.DisplayId; preset.primaryDisplay = false; } else { preset.primaryDisplay = true; preset.displayName = null; + preset.DisplayId = null; } AddOrUpdateItem(); @@ -1181,37 +1089,19 @@ namespace ColorControl.Services.NVIDIA return; } + var display = displays.FirstOrDefault(d => d.ToString() == displayField.Value.ToString()); + var preset = new NvPreset(); preset.name = nameField.Value.ToString(); preset.primaryDisplay = displayField.Value.ToString() == "Primary display"; - preset.displayName = !preset.primaryDisplay ? displays.FirstOrDefault(d => d.ToString() == displayField.Value.ToString())?.Display?.Name : null; + preset.DisplayId = preset.primaryDisplay ? null : display?.DisplayId; + preset.displayName = preset.primaryDisplay ? null : display?.Name; AskColorData(preset, colorSelectField.ValueAsBool); AskResolution(preset, resolutionSelectField.ValueAsBool); AskRefreshRate(preset, refreshRateSelectField.ValueAsBool); AddOrUpdateItem(preset); - - //var presets = NvPreset.GetDefaultPresets(); - //var added = false; - - //foreach (var preset in presets) - //{ - // if (!_nvService.GetPresets().Any(x => x.colorData.Equals(preset.colorData))) - // { - // AddOrUpdateItem(preset); - // added = true; - // } - //} - - //if (added) - //{ - // MessageForms.InfoOk("Missing presets added."); - //} - //else - //{ - // MessageForms.InfoOk("All presets for every color setting already exist."); - //} } private void AskColorData(NvPreset preset, bool ask = true) @@ -2164,5 +2054,64 @@ namespace ColorControl.Services.NVIDIA public void Init() { } + + private void mnuRefreshRate_DropDownOpening(object sender, EventArgs e) + { + var preset = GetSelectedNvPreset(true); + + if (preset == null) + { + return; + } + + miRefreshRateIncluded.Visible = !preset.IsDisplayPreset; + miRefreshRateIncluded.Checked = preset.DisplayConfig.ApplyRefreshRate; + + var refreshRates = _nvService.GetAvailableRefreshRatesV2(preset); + + while (mnuRefreshRate.DropDownItems.Count > 1) + { + mnuRefreshRate.DropDownItems.RemoveAt(mnuRefreshRate.DropDownItems.Count - 1); + } + + foreach (var refreshRate in refreshRates) + { + var item = mnuRefreshRate.DropDownItems.AddCustom(refreshRate.ToString() + "Hz") as ToolStripMenuItem; + item.Tag = refreshRate; + item.Click += refreshRateMenuItem_Click; + item.Checked = refreshRate.Equals(preset.DisplayConfig.RefreshRate); + } + + UpdateNvPresetMenuFont(); + } + + private void mnuNvResolution_DropDownOpening(object sender, EventArgs e) + { + var preset = GetSelectedNvPreset(true); + + miNvResolutionIncluded.Checked = preset.DisplayConfig.ApplyResolution; + + mnuNvActiveResolution.DropDownItems.Clear(); + mnuNvVirtualResolution.DropDownItems.Clear(); + + var modes = _nvService.GetAvailableResolutionsV2(preset); + foreach (var mode in modes) + { + var item = mnuNvActiveResolution.DropDownItems.AddCustom(mode.ToString()) as ToolStripMenuItem; + item.Tag = mode; + item.Click += resolutionNvMenuItem_Click; + item.Checked = mode.ActiveWidth == preset.DisplayConfig.Resolution.ActiveWidth && mode.ActiveHeight == preset.DisplayConfig.Resolution.ActiveHeight; + } + + foreach (var mode in modes) + { + var item = mnuNvVirtualResolution.DropDownItems.AddCustom(mode.ToString()) as ToolStripMenuItem; + item.Tag = mode; + item.Click += virtualResolutionNvMenuItem_Click; + item.Checked = mode.VirtualWidth == preset.DisplayConfig.Resolution.VirtualWidth && mode.VirtualHeight == preset.DisplayConfig.Resolution.VirtualHeight; + } + + UpdateNvPresetMenuFont(); + } } } diff --git a/ColorControl/Services/NVIDIA/NvPreset.cs b/ColorControl/Services/NVIDIA/NvPreset.cs index 3b8d7dd..0ed1c37 100644 --- a/ColorControl/Services/NVIDIA/NvPreset.cs +++ b/ColorControl/Services/NVIDIA/NvPreset.cs @@ -30,6 +30,7 @@ namespace ColorControl.Services.NVIDIA public DisplayConfig DisplayConfig { get; set; } public bool primaryDisplay { get; set; } public string displayName { get; set; } + public string DisplayId { get; set; } public uint ditheringBits { get; set; } public uint ditheringMode { get; set; } public bool applyOther { get; set; } @@ -88,6 +89,7 @@ namespace ColorControl.Services.NVIDIA primaryDisplay = preset.primaryDisplay; displayName = preset.displayName; + DisplayId = preset.DisplayId; var colorData = preset.colorData; this.colorData = new ColorData(colorData.ColorFormat, dynamicRange: colorData.DynamicRange, colorDepth: colorData.ColorDepth, colorSelectionPolicy: ColorDataSelectionPolicy.User); @@ -139,7 +141,7 @@ namespace ColorControl.Services.NVIDIA isCurrent ? "Current settings" : name }; - var display = isCurrent ? displayName : string.Format("{0}", primaryDisplay ? "Primary" : displayName); + var display = isCurrent ? displayName : string.Format("{0}", primaryDisplay ? "Primary" : !displayName.IsNullOrEmpty() ? displayName : DisplayId); values.Add(display); var colorSettings = FormatDisplaySetting(string.Format("{0}, {1}, {2}, {3}", colorData.ColorDepth, colorData.ColorFormat, colorData.DynamicRange, colorData.Colorimetry), isCurrent, applyColorData); diff --git a/ColorControl/Services/NVIDIA/NvService.cs b/ColorControl/Services/NVIDIA/NvService.cs index de391e4..19a923a 100644 --- a/ColorControl/Services/NVIDIA/NvService.cs +++ b/ColorControl/Services/NVIDIA/NvService.cs @@ -12,6 +12,7 @@ using Newtonsoft.Json; using novideo_srgb; using nspector.Common; using nspector.Common.Meta; +using NStandard; using NvAPIWrapper.Display; using NvAPIWrapper.GPU; using NvAPIWrapper.Native; @@ -275,9 +276,9 @@ namespace ColorControl.Services.NVIDIA } } - public Display GetCurrentDisplay() + public Display GetCurrentDisplay(bool checkDisplays = true) { - if (!HasDisplaysAttached()) + if (checkDisplays && !HasDisplaysAttached()) { _currentDisplay = null; return null; @@ -341,12 +342,19 @@ namespace ColorControl.Services.NVIDIA private Display GetPresetDisplay(NvPreset preset) { + if (preset.Display != null) + { + return preset.Display; + } + if (preset.primaryDisplay) { return GetPrimaryDisplay(); } - return Display.GetDisplays().FirstOrDefault(x => x.Name.Equals(preset.displayName)); + var displays = GetSimpleDisplayInfos(); + + return displays.FirstOrDefault(d => d.DisplayId == preset.DisplayId)?.Display; } public Display GetPrimaryDisplay() @@ -937,25 +945,14 @@ namespace ColorControl.Services.NVIDIA if (setRegistryKey) { - var displays = WindowsDisplayAPI.Display.GetDisplays(); - var path = displays.FirstOrDefault(x => x.DisplayName == display.Name)?.DevicePath; + var info = CCD.GetDisplayInfo(display.Name); + var regId = info?.DisplayId; - if (path == null) + if (regId.IsNullOrEmpty()) { - Logger.Debug($"Cannot find path for display {display.Name}"); return false; } - var parts = path.Split('#'); - - if (parts.Length < 2) - { - Logger.Debug($"Incorrect path for display {display.Name}"); - return false; - } - - var regId = parts[1]; - result = SetDitherRegistryKey(regId, (uint)state, bits, mode); if (restartDriver) @@ -1064,13 +1061,15 @@ namespace ColorControl.Services.NVIDIA SetCurrentDisplay(preset); } - var display = GetCurrentDisplay(); + var display = GetCurrentDisplay(false); if (display == null) { return []; } - var desktopRect = GetDesktopRect(display); + var desktopRect = preset?.DisplayConfig.ApplyResolution == true && preset?.DisplayConfig.Resolution.ActiveWidth > 0 ? + new Rectangle(0, 0, (int)preset.DisplayConfig.Resolution.ActiveWidth, (int)preset.DisplayConfig.Resolution.ActiveHeight) : + GetDesktopRect(display); return GetAvailableRefreshRatesV2(display.Name, desktopRect.Width, desktopRect.Height); } @@ -1082,7 +1081,7 @@ namespace ColorControl.Services.NVIDIA SetCurrentDisplay(preset); } - var display = GetCurrentDisplay(); + var display = GetCurrentDisplay(false); if (display == null) { return []; @@ -1218,6 +1217,11 @@ namespace ColorControl.Services.NVIDIA { var displayDevice = display.DisplayDevice; + if (displayDevice.ConnectionType != NvAPIWrapper.Native.GPU.MonitorConnectionType.HDMI) + { + return null; + } + return Logger.Swallow(() => displayDevice.HDMIVideoFrameOverrideInformation) ?? Logger.Swallow(() => displayDevice.HDMIVideoFrameCurrentInformation); } @@ -1237,7 +1241,10 @@ namespace ColorControl.Services.NVIDIA public void SetScaling(Display display, Scaling scaling) { - var pathInfo = GetPathInfoForDisplay(display); + var pathInfos = DisplayApi.GetDisplayConfig().ToList(); + + var pathInfo = pathInfos.FirstOrDefault(c => c.TargetsInfo.Any(ti => ti.DisplayId == display.DisplayDevice.DisplayId)); + var pathInfoIndex = pathInfos.IndexOf(pathInfo); var pathTargetInfo = pathInfo.TargetsInfo.FirstOrDefault(ti => ti.DisplayId == display.DisplayDevice.DisplayId); @@ -1254,7 +1261,10 @@ namespace ColorControl.Services.NVIDIA var newPathInfo = new PathInfoV2(new[] { newPathTargetInfo }, pathInfo.SourceModeInfo); - DisplayApi.SetDisplayConfig(new IPathInfo[] { newPathInfo }, DisplayConfigFlags.SaveToPersistence); + var newPathInfos = pathInfos.ToArray(); + newPathInfos[pathInfoIndex] = newPathInfo; + + DisplayApi.SetDisplayConfig(newPathInfos, DisplayConfigFlags.SaveToPersistence); } private IPathTargetInfo? GetTargetInfoForDisplay(Display display) @@ -1431,9 +1441,7 @@ namespace ColorControl.Services.NVIDIA foreach (var display in displays) { - var name = FormUtils.ExtendedDisplayName(display.Name); - - var displayInfo = new NvDisplayInfo(display, null, null, name); + var displayInfo = new NvDisplayInfo(display, null, null); list.Add(displayInfo); } @@ -1445,7 +1453,6 @@ namespace ColorControl.Services.NVIDIA { try { - var displays = GetDisplays(); var list = new List(); if (refreshSettings) @@ -1453,12 +1460,15 @@ namespace ColorControl.Services.NVIDIA RefreshProfileSettings(); } - foreach (var display in displays) - { - var preset = GetPresetForDisplay(display, true, displays.Count()); + var displayInfos = GetSimpleDisplayInfos(); + foreach (var displayInfo in displayInfos) + { + var preset = GetPresetForDisplay(displayInfo, true, displayInfos.Count()); var values = preset.GetDisplayValues(_globalContext.Config); - var displayInfo = new NvDisplayInfo(display, values, preset.InfoLine, preset.displayName); + + displayInfo.Values = values; + displayInfo.InfoLine = preset.InfoLine; list.Add(displayInfo); } @@ -1479,29 +1489,31 @@ namespace ColorControl.Services.NVIDIA } } - public NvPreset GetPresetForDisplay(string displayName, bool driverSettings = false) + public NvPreset GetPresetForDisplay(string name, bool driverSettings = false) { - var displays = GetDisplays(); - - var display = displays.FirstOrDefault(d => displayName.StartsWith(d.Name)); + var displays = GetSimpleDisplayInfos(); + var display = displays.FirstOrDefault(d => name.StartsWith(d.Name)); return GetPresetForDisplay(display, driverSettings, displays.Count()); } - public NvPreset GetPresetForDisplay(Display display, bool driverSettings = false, int displayCount = 1) + public NvPreset GetPresetForDisplay(NvDisplayInfo displayInfo, bool driverSettings = false, int displayCount = 1) { - if (display == null) + if (displayInfo == null) { return null; } + var display = displayInfo.Display; + var isPrimaryDisplay = displayCount == 1 || display.DisplayDevice.DisplayId == DisplayDevice.GetGDIPrimaryDisplayDevice()?.DisplayId; var preset = new NvPreset { Display = display, IsDisplayPreset = true, applyColorData = false, primaryDisplay = isPrimaryDisplay }; preset.HDREnabled = IsHDREnabled(display); preset.HdrSettings.OutputMode = preset.HDREnabled && OutputModeAvailable ? GetOutputMode(display) : null; - preset.displayName = FormUtils.ExtendedDisplayName(display.Name); + preset.DisplayId = displayInfo.DisplayId; + preset.displayName = displayInfo.Name; preset.colorData = GetCurrentColorData(display); preset.ColorEnhancementSettings = GetCurrentColorEnhancements(display); preset.HdmiInfoFrameSettings = GetHdmiSettings(display); diff --git a/ColorControl/Services/Samsung/SamsungDevice.cs b/ColorControl/Services/Samsung/SamsungDevice.cs index 7eef059..2e5d41b 100644 --- a/ColorControl/Services/Samsung/SamsungDevice.cs +++ b/ColorControl/Services/Samsung/SamsungDevice.cs @@ -710,7 +710,7 @@ namespace ColorControl.Services.Samsung SubLabel = "Both types will not reset your settings. 'FactoryMenu' is recommended for 2024 series but will also work for older ones. Click 'Next >' to continue or 'X' to stop", FieldType = FieldType.DropDown, Values = serviceMenuTypes, - Value = ServiceMenuType.HospitalityMenu + Value = ServiceMenuType.FactoryMenu }; if (!MessageForms.ShowDialog($"Access Service Menu", [serviceMenuTypeField], okButtonText: "Next >").Any()) diff --git a/ColorControl/XForms/ColorProfileViewModel.cs b/ColorControl/XForms/ColorProfileViewModel.cs index ceae6df..9bb74fe 100644 --- a/ColorControl/XForms/ColorProfileViewModel.cs +++ b/ColorControl/XForms/ColorProfileViewModel.cs @@ -53,7 +53,7 @@ public class CustomDisplay public override string ToString() { - return $"{FormUtils.ExtendedDisplayName(Display.DisplayName)} on {Display.Adapter.DeviceName}"; + return $"{CCD.GetDisplayInfo(Display.DisplayName)} on {Display.Adapter.DeviceName}"; } } diff --git a/Shared/Contracts/Config.cs b/Shared/Contracts/Config.cs index 3fae172..b581e7c 100644 --- a/Shared/Contracts/Config.cs +++ b/Shared/Contracts/Config.cs @@ -41,6 +41,7 @@ public List Modules { get; set; } public bool UseRawInput { get; set; } public bool SetMinTmlAndMaxTml { get; set; } + public bool DisableErrorPopupWhenApplyingPreset { get; set; } public Config() { diff --git a/Shared/EventDispatcher/WindowMessageDispatcher.cs b/Shared/EventDispatcher/WindowMessageDispatcher.cs index a3ce468..a44dca1 100644 --- a/Shared/EventDispatcher/WindowMessageDispatcher.cs +++ b/Shared/EventDispatcher/WindowMessageDispatcher.cs @@ -19,6 +19,7 @@ public class WindowMessageDispatcher : EventDispatcher public const string Event_WindowMessageHotKey = "WindowMessageHotKey"; public const string Event_WindowMessageInput = "WindowMessageInput"; public const string Event_WindowMessageQueryEndSession = "WindowMessageQueryEndSession"; + public const string Event_WindowMessageEndSession = "WindowMessageEndSession"; public const string Event_WindowMessageClose = "WindowMessageClose"; public const string Event_WindowMessagePowerBroadcast = "WindowMessagePowerBroadcast"; public const string Event_WindowMessageShowWindow = "WindowMessageShowWindow"; @@ -27,12 +28,14 @@ public class WindowMessageDispatcher : EventDispatcher private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); private readonly GlobalContext _globalContext; - public DummyForm MessageForm { get; set; } + public DummyForm MessageForm { get; private set; } + private static Dictionary Messages = new() { { NativeConstants.WM_HOTKEY, Event_WindowMessageHotKey }, { NativeConstants.WM_INPUT, Event_WindowMessageInput }, { NativeConstants.WM_QUERYENDSESSION, Event_WindowMessageQueryEndSession }, + { NativeConstants.WM_ENDSESSION, Event_WindowMessageEndSession }, { NativeConstants.WM_CLOSE, Event_WindowMessageClose }, { NativeConstants.WM_POWERBROADCAST, Event_WindowMessagePowerBroadcast }, { NativeConstants.WM_SHOWWINDOW, Event_WindowMessageShowWindow }, @@ -60,25 +63,12 @@ public class WindowMessageDispatcher : EventDispatcher { public event EventHandler OnMessage; - private bool _systemShutdown; - public DummyForm() { FormBorderStyle = FormBorderStyle.None; ShowInTaskbar = false; Load += DummyForm_Load; Shown += DummyForm_Shown; - FormClosing += DummyForm_FormClosing; - } - - private void DummyForm_FormClosing(object sender, FormClosingEventArgs e) - { - Logger.Debug($"FormClosing: {_systemShutdown}"); - - if (_systemShutdown) - { - OnMessage?.Invoke(this, new Message { Msg = NativeConstants.WM_CLOSE }); - } } private void DummyForm_Shown(object sender, EventArgs e) @@ -95,7 +85,7 @@ public class WindowMessageDispatcher : EventDispatcher { if (m.Msg == NativeConstants.WM_QUERYENDSESSION) { - _systemShutdown = true; + Logger.Debug("WM_QUERYENDSESSION"); } OnMessage?.Invoke(this, m); diff --git a/Shared/Forms/DarkModeUtils.cs b/Shared/Forms/DarkModeUtils.cs index ec37d73..bdb9ec6 100644 --- a/Shared/Forms/DarkModeUtils.cs +++ b/Shared/Forms/DarkModeUtils.cs @@ -12,6 +12,7 @@ namespace ColorControl.Shared.Forms private static ToolStripRenderer _defaultRenderer; private static Type[] _windowColorTypes = new[] { typeof(GroupBox), typeof(TabPage), typeof(UserControl) }; public const int DWMWA_USE_IMMERSIVE_DARK_MODE = 20; + public static readonly Color ListViewDarkModeBackColor = Color.FromArgb(80, 80, 80); public class DarkModeToolStripRenderer : ToolStripProfessionalRenderer { diff --git a/Shared/Forms/FormUtils.cs b/Shared/Forms/FormUtils.cs index 634daf9..55718f3 100644 --- a/Shared/Forms/FormUtils.cs +++ b/Shared/Forms/FormUtils.cs @@ -1,6 +1,5 @@ using ColorControl.Shared.Common; using ColorControl.Shared.Contracts; -using ColorControl.Shared.Native; using NStandard; using NWin32; using System.Collections; @@ -523,18 +522,6 @@ namespace ColorControl.Shared.Forms eventHandlerList.Dispose(); } - public static string ExtendedDisplayName(string displayName) - { - var name = displayName; - var screen = Screen.AllScreens.FirstOrDefault(x => x.DeviceName.Equals(name)); - if (screen != null) - { - name += " (" + screen.DeviceFriendlyName() + ")"; - } - - return name; - } - public static IntPtr GetMonitorForDisplayName(string displayName) { var name = displayName; diff --git a/Shared/Native/CCD.cs b/Shared/Native/CCD.cs index e9c2f84..8c55c7a 100644 --- a/Shared/Native/CCD.cs +++ b/Shared/Native/CCD.cs @@ -1,6 +1,7 @@ using ColorControl.Shared.Contracts; using ColorControl.Shared.Forms; using MHC2Gen; +using NStandard; using NWin32; using System.ComponentModel; using System.IO; @@ -9,6 +10,30 @@ using System.Runtime.InteropServices; namespace ColorControl.Shared.Native { + public class DisplayInfo(string displayName, string friendlyName, string devicePath) + { + public string DisplayName { get; } = displayName; + public string FriendlyName { get; } = friendlyName; + public string DevicePath { get; } = devicePath; + + private string _displayId; + public string DisplayId + { + get + { + if (_displayId == null) + { + _displayId = CCD.GetDisplayIdByPath(DevicePath); + } + return _displayId; + } + } + + public string ExtendedName => $"{FriendlyName} ({DisplayId})"; + + public override string ToString() => ExtendedName; + } + // This class takes care of wrapping "Connecting and Configuring Displays(CCD) Win32 API" public static class CCD { @@ -25,6 +50,25 @@ namespace ColorControl.Shared.Native Clone } + public static string GetDisplayIdByPath(string displayPath) + { + if (displayPath == null) + { + Logger.Debug($"Cannot find path for display with path {displayPath}"); + return null; + } + + var parts = displayPath.Split('#'); + + if (parts.Length < 2) + { + Logger.Debug($"Incorrect path for display with path {displayPath}"); + return null; + } + + return parts[1]; + } + public static double GetDpiForSystem() { var dpi = NativeMethods.GetDpiForSystem(); @@ -119,28 +163,60 @@ namespace ColorControl.Shared.Native return false; } + var pathIndex = pathsArray.IndexOf(p => MatchDisplayNames(p, displayName)); + + if (pathIndex == -1) + { + return false; + } + + var sourceIndex = pathsArray[pathIndex].sourceInfo.modeInfoIdx; + var targetIndex = pathsArray[pathIndex].targetInfo.modeInfoIdx; + var resolution = displayConfig.Resolution; var refreshRate = displayConfig.RefreshRate; - foreach (var path in pathsArray) + var isModeChangeNeeded = false; + + if (modesArray[targetIndex].targetMode.targetVideoSignalInfo.vSyncFreq.numerator != refreshRate.Numerator || + modesArray[targetIndex].targetMode.targetVideoSignalInfo.vSyncFreq.denominator != refreshRate.Denominator) { - if (!MatchDisplayNames(path, displayName)) - { - continue; - } + modesArray[targetIndex].targetMode.targetVideoSignalInfo.vSyncFreq = new DisplayConfigRational { denominator = refreshRate.Denominator, numerator = refreshRate.Numerator }; + isModeChangeNeeded = true; + } - var sourceIndex = path.sourceInfo.modeInfoIdx; - var targetIndex = path.targetInfo.modeInfoIdx; - var sourceMode = modesArray[sourceIndex]; - var targetMode = modesArray[targetIndex]; + if (modesArray[targetIndex].targetMode.targetVideoSignalInfo.activeSize.cx != resolution.ActiveWidth || + modesArray[targetIndex].targetMode.targetVideoSignalInfo.activeSize.cy != resolution.ActiveHeight) + { + modesArray[targetIndex].targetMode.targetVideoSignalInfo.activeSize.cx = resolution.ActiveWidth; + modesArray[targetIndex].targetMode.targetVideoSignalInfo.activeSize.cy = resolution.ActiveHeight; + isModeChangeNeeded = true; + } - targetMode.targetMode.targetVideoSignalInfo.vSyncFreq = new DisplayConfigRational { denominator = refreshRate.Denominator, numerator = refreshRate.Numerator }; - targetMode.targetMode.targetVideoSignalInfo.activeSize.cx = resolution.ActiveWidth; - targetMode.targetMode.targetVideoSignalInfo.activeSize.cy = resolution.ActiveHeight; + if (modesArray[sourceIndex].sourceMode.width != resolution.VirtualWidth || modesArray[sourceIndex].sourceMode.height != resolution.VirtualHeight) + { + modesArray[sourceIndex].sourceMode.width = resolution.VirtualWidth; + modesArray[sourceIndex].sourceMode.height = resolution.VirtualHeight; + isModeChangeNeeded = true; + } - sourceMode.sourceMode.width = resolution.VirtualWidth; - sourceMode.sourceMode.height = resolution.VirtualHeight; + var newScaling = displayConfig.Scaling == DisplayConfigScaling.Zero ? DisplayConfigScaling.Identity : displayConfig.Scaling; + if (pathsArray[pathIndex].targetInfo.scaling != newScaling) + { + pathsArray[pathIndex].targetInfo.scaling = newScaling; + isModeChangeNeeded = true; + } + var newRotation = displayConfig.Rotation == DisplayConfigRotation.Zero ? DisplayConfigRotation.Identity : displayConfig.Rotation; + if (pathsArray[pathIndex].targetInfo.rotation != newRotation) + { + pathsArray[pathIndex].targetInfo.rotation = newRotation; + isModeChangeNeeded = true; + } + //pathsArray[pathIndex].targetInfo.refreshRate = new DisplayConfigRational { numerator = displayConfig.RefreshRate.Numerator, denominator = displayConfig.RefreshRate.Denominator }; + + if (isModeChangeNeeded) + { var flags = SdcFlags.Apply | SdcFlags.UseSuppliedDisplayConfig | SdcFlags.AllowChanges; if (updateRegistry) @@ -148,17 +224,10 @@ namespace ColorControl.Shared.Native flags |= SdcFlags.SaveToDatabase; } - var path2 = path; - path2.targetInfo.scaling = displayConfig.Scaling == DisplayConfigScaling.Zero ? DisplayConfigScaling.Identity : displayConfig.Scaling; - path2.targetInfo.rotation = displayConfig.Rotation == DisplayConfigRotation.Zero ? DisplayConfigRotation.Identity : displayConfig.Rotation; - path2.targetInfo.refreshRate = new DisplayConfigRational { numerator = displayConfig.RefreshRate.Numerator, denominator = displayConfig.RefreshRate.Denominator }; - - err = NativeMethods.SetDisplayConfig(1, [path2], 2, [targetMode, sourceMode], flags); - - return err == 0; + err = NativeMethods.SetDisplayConfig(pathCount, pathsArray, modeCount, modesArray, flags); } - return false; + return err == 0; } finally { @@ -363,7 +432,7 @@ namespace ColorControl.Shared.Native public static bool GetUsePerUserDisplayProfiles(string displayName) { - var deviceKey = GetDisplayDeviceKey(displayName); + var deviceKey = GetDisplayDeviceRegistryKey(displayName); if (deviceKey == null) { @@ -385,7 +454,7 @@ namespace ColorControl.Shared.Native public static bool SetUsePerUserDisplayProfiles(string displayName, bool usePerUserProfiles) { - var deviceKey = GetDisplayDeviceKey(displayName); + var deviceKey = GetDisplayDeviceRegistryKey(displayName); if (deviceKey == null) { @@ -397,7 +466,7 @@ namespace ColorControl.Shared.Native return result; } - private static string GetDisplayDeviceKey(string displayName) + private static string GetDisplayDeviceRegistryKey(string displayName) { var hMonitor = FormUtils.GetMonitorForDisplayName(displayName); @@ -423,6 +492,33 @@ namespace ColorControl.Shared.Native return dd.DeviceKey; } + public static DisplayInfo GetDisplayInfo(string displayName) + { + return ExecuteForModeConfig((modeInfo) => + { + if (modeInfo.infoType == DisplayConfigModeInfoType.Target) + { + var requestpacket = new DISPLAYCONFIG_TARGET_DEVICE_NAME(); + requestpacket.header = new DISPLAYCONFIG_DEVICE_INFO_HEADER(); + requestpacket.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME; + requestpacket.header.size = Marshal.SizeOf(); + + requestpacket.header.adapterId = modeInfo.adapterId; + requestpacket.header.id = modeInfo.id; + + var err = NativeMethods.DisplayConfigGetDeviceInfo(ref requestpacket); + + if (err == NativeConstants.ERROR_SUCCESS) + { + return (new DisplayInfo(displayName, requestpacket.monitorFriendlyDeviceName, requestpacket.monitorDevicePath), false); + } + } + + return (null, true); + }, displayName + ); + } + public static uint GetSDRWhiteLevel(string displayName = null) { return ExecuteForModeConfig((modeInfo) => @@ -1219,7 +1315,7 @@ namespace ColorControl.Shared.Native [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] public string monitorFriendlyDeviceName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] - public string monitorDevicePat; + public string monitorDevicePath; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] diff --git a/Shared/Native/DXWrapper.cs b/Shared/Native/DXWrapper.cs index 55445e1..b2e4a7c 100644 --- a/Shared/Native/DXWrapper.cs +++ b/Shared/Native/DXWrapper.cs @@ -3851,9 +3851,9 @@ public class DXWrapper : DXNativeMethods //ADAPTER_DESC1 aDAPTER_DESC1 = new ADAPTER_DESC1(); //adapter.GetDesc1(out aDAPTER_DESC1); - for (var o = 0; ; o++) + for (uint o = 0; ; o++) { - if (!Ok(adapter.EnumOutputs(0, out var output))) + if (!Ok(adapter.EnumOutputs(o, out var output))) { break; } diff --git a/Shared/Native/ScreenInterrogatory.cs b/Shared/Native/ScreenInterrogatory.cs deleted file mode 100644 index 72b260e..0000000 --- a/Shared/Native/ScreenInterrogatory.cs +++ /dev/null @@ -1,309 +0,0 @@ -using System.ComponentModel; -using System.Runtime.InteropServices; - -namespace ColorControl.Shared.Native -{ - 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 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; - } - - } -}