diff --git a/DisplayMagician/NativeMethods.cs b/DisplayMagician/NativeMethods.cs index a595283..1d60c2b 100644 --- a/DisplayMagician/NativeMethods.cs +++ b/DisplayMagician/NativeMethods.cs @@ -131,6 +131,22 @@ namespace DisplayMagician [SuppressUnmanagedCodeSecurity] internal static class NativeMethods { + + [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] + private static extern IntPtr SendMessageTimeout(IntPtr windowHandle, uint message, IntPtr wordParameter, IntPtr longParameter, SendMessageTimeoutFlag flag, uint timeout, out IntPtr resultHandle); + + [Flags] + public enum SendMessageTimeoutFlag : uint + { + SMTO_NORMAL = 0x0, + SMTO_BLOCK = 0x1, + SMTO_ABORTIFHUNG = 0x2, + SMTO_NOTIMEOUTIFNOTHUNG = 0x8, + SMTO_ERRORONEXIT = 0x20 + } + + public const Int32 WM_WININICHANGE = 0x001A; + /// /// Delegate declaration that matches WndProc signatures. /// diff --git a/DisplayMagician/Properties/AssemblyInfo.cs b/DisplayMagician/Properties/AssemblyInfo.cs index 74d90ff..a7aaa4c 100644 --- a/DisplayMagician/Properties/AssemblyInfo.cs +++ b/DisplayMagician/Properties/AssemblyInfo.cs @@ -26,8 +26,8 @@ using System.Resources; [assembly: Guid("e4ceaf5e-ad01-4695-b179-31168eb74c48")] // Version information -[assembly: AssemblyVersion("2.2.0.112")] -[assembly: AssemblyFileVersion("2.2.0.112")] +[assembly: AssemblyVersion("2.2.0.152")] +[assembly: AssemblyFileVersion("2.2.0.152")] [assembly: NeutralResourcesLanguageAttribute( "en" )] [assembly: CLSCompliant(true)] diff --git a/DisplayMagician/UIForms/DisplayProfileForm.cs b/DisplayMagician/UIForms/DisplayProfileForm.cs index 1029f74..9dbb97f 100644 --- a/DisplayMagician/UIForms/DisplayProfileForm.cs +++ b/DisplayMagician/UIForms/DisplayProfileForm.cs @@ -629,6 +629,7 @@ namespace DisplayMagician.UIForms // otherwise we'll save it only when the user wants to save this profile. if (_saveOrRenameMode == "rename" && profileSettingsForm.ProfileSettingChanged) { + //_selectedProfile = profileSettingsForm.Profile; ProfileRepository.SaveProfiles(); } } diff --git a/DisplayMagician/UIForms/ProfileSettingsForm.Designer.cs b/DisplayMagician/UIForms/ProfileSettingsForm.Designer.cs index 36a61fa..3cb1e39 100644 --- a/DisplayMagician/UIForms/ProfileSettingsForm.Designer.cs +++ b/DisplayMagician/UIForms/ProfileSettingsForm.Designer.cs @@ -40,8 +40,13 @@ namespace DisplayMagician.UIForms this.btn_select = new System.Windows.Forms.Button(); this.lbl_style = new System.Windows.Forms.Label(); this.cmb_wallpaper_display_mode = new System.Windows.Forms.ComboBox(); + this.gb_taskbar = new System.Windows.Forms.GroupBox(); + this.cmb_forced_taskbar_location = new System.Windows.Forms.ComboBox(); + this.rb_default_taskbar = new System.Windows.Forms.RadioButton(); + this.rb_forced_taskbar = new System.Windows.Forms.RadioButton(); this.gb_general.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.pb_wallpaper)).BeginInit(); + this.gb_taskbar.SuspendLayout(); this.SuspendLayout(); // // btn_back @@ -52,7 +57,7 @@ namespace DisplayMagician.UIForms this.btn_back.FlatAppearance.MouseOverBackColor = System.Drawing.Color.Brown; this.btn_back.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.btn_back.ForeColor = System.Drawing.Color.White; - this.btn_back.Location = new System.Drawing.Point(476, 436); + this.btn_back.Location = new System.Drawing.Point(476, 554); this.btn_back.Name = "btn_back"; this.btn_back.Size = new System.Drawing.Size(75, 23); this.btn_back.TabIndex = 9; @@ -73,7 +78,7 @@ namespace DisplayMagician.UIForms this.gb_general.Controls.Add(this.cmb_wallpaper_display_mode); this.gb_general.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.gb_general.ForeColor = System.Drawing.Color.White; - this.gb_general.Location = new System.Drawing.Point(27, 27); + this.gb_general.Location = new System.Drawing.Point(27, 131); this.gb_general.Name = "gb_general"; this.gb_general.Size = new System.Drawing.Size(525, 381); this.gb_general.TabIndex = 11; @@ -205,12 +210,62 @@ namespace DisplayMagician.UIForms this.cmb_wallpaper_display_mode.TabIndex = 12; this.cmb_wallpaper_display_mode.SelectedIndexChanged += new System.EventHandler(this.cmb_wallpaper_display_mode_SelectedIndexChanged); // + // gb_taskbar + // + this.gb_taskbar.Controls.Add(this.rb_default_taskbar); + this.gb_taskbar.Controls.Add(this.rb_forced_taskbar); + this.gb_taskbar.Controls.Add(this.cmb_forced_taskbar_location); + this.gb_taskbar.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.gb_taskbar.ForeColor = System.Drawing.Color.White; + this.gb_taskbar.Location = new System.Drawing.Point(27, 22); + this.gb_taskbar.Name = "gb_taskbar"; + this.gb_taskbar.Size = new System.Drawing.Size(524, 100); + this.gb_taskbar.TabIndex = 12; + this.gb_taskbar.TabStop = false; + this.gb_taskbar.Text = "TaskBar Settings"; + // + // cmb_forced_taskbar_location + // + this.cmb_forced_taskbar_location.Enabled = false; + this.cmb_forced_taskbar_location.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.cmb_forced_taskbar_location.FormattingEnabled = true; + this.cmb_forced_taskbar_location.Location = new System.Drawing.Point(220, 59); + this.cmb_forced_taskbar_location.Name = "cmb_forced_taskbar_location"; + this.cmb_forced_taskbar_location.Size = new System.Drawing.Size(189, 24); + this.cmb_forced_taskbar_location.TabIndex = 13; + this.cmb_forced_taskbar_location.SelectedIndexChanged += new System.EventHandler(this.cmb_forced_taskbar_location_SelectedIndexChanged); + // + // rb_default_taskbar + // + this.rb_default_taskbar.AutoSize = true; + this.rb_default_taskbar.Checked = true; + this.rb_default_taskbar.Location = new System.Drawing.Point(28, 34); + this.rb_default_taskbar.Name = "rb_default_taskbar"; + this.rb_default_taskbar.Size = new System.Drawing.Size(288, 20); + this.rb_default_taskbar.TabIndex = 24; + this.rb_default_taskbar.TabStop = true; + this.rb_default_taskbar.Text = "Leave TaskBar Location as set by Windows"; + this.rb_default_taskbar.UseVisualStyleBackColor = true; + this.rb_default_taskbar.CheckedChanged += new System.EventHandler(this.rb_default_taskbar_CheckedChanged); + // + // rb_forced_taskbar + // + this.rb_forced_taskbar.AutoSize = true; + this.rb_forced_taskbar.Location = new System.Drawing.Point(28, 60); + this.rb_forced_taskbar.Name = "rb_forced_taskbar"; + this.rb_forced_taskbar.Size = new System.Drawing.Size(190, 20); + this.rb_forced_taskbar.TabIndex = 23; + this.rb_forced_taskbar.Text = "Force TaskBar Location to :"; + this.rb_forced_taskbar.UseVisualStyleBackColor = true; + this.rb_forced_taskbar.CheckedChanged += new System.EventHandler(this.rb_forced_taskbar_CheckedChanged); + // // ProfileSettingsForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.BackColor = System.Drawing.Color.Black; - this.ClientSize = new System.Drawing.Size(580, 483); + this.ClientSize = new System.Drawing.Size(580, 594); + this.Controls.Add(this.gb_taskbar); this.Controls.Add(this.gb_general); this.Controls.Add(this.btn_back); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; @@ -227,6 +282,8 @@ namespace DisplayMagician.UIForms this.gb_general.ResumeLayout(false); this.gb_general.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.pb_wallpaper)).EndInit(); + this.gb_taskbar.ResumeLayout(false); + this.gb_taskbar.PerformLayout(); this.ResumeLayout(false); } @@ -243,5 +300,9 @@ namespace DisplayMagician.UIForms private System.Windows.Forms.RadioButton rb_leave_wallpaper; private System.Windows.Forms.RadioButton rb_clear_wallpaper; private System.Windows.Forms.RadioButton rb_apply_wallpaper; + private System.Windows.Forms.GroupBox gb_taskbar; + private System.Windows.Forms.RadioButton rb_default_taskbar; + private System.Windows.Forms.RadioButton rb_forced_taskbar; + private System.Windows.Forms.ComboBox cmb_forced_taskbar_location; } } \ No newline at end of file diff --git a/DisplayMagician/UIForms/ProfileSettingsForm.cs b/DisplayMagician/UIForms/ProfileSettingsForm.cs index dc3d93e..985ea66 100644 --- a/DisplayMagician/UIForms/ProfileSettingsForm.cs +++ b/DisplayMagician/UIForms/ProfileSettingsForm.cs @@ -1,4 +1,5 @@ using DisplayMagicianShared; +using DisplayMagicianShared.Windows; //using Microsoft.Win32; using NHotkey; using NHotkey.WindowsForms; @@ -19,6 +20,7 @@ namespace DisplayMagician.UIForms private Dictionary wallpaperStyleText = new Dictionary(); Bitmap wallpaperImage = null; + private Dictionary forcedTaskBarEdgeText = new Dictionary(); private bool _profileSettingChanged = false; public ProfileSettingsForm() @@ -38,6 +40,28 @@ namespace DisplayMagician.UIForms cmb_wallpaper_display_mode.DisplayMember = "Value"; cmb_wallpaper_display_mode.ValueMember = "Text"; cmb_wallpaper_display_mode.DataSource = new BindingSource(wallpaperStyleText, null); + + // Populate the Forced Taskbar Location dictionary + if (Utils.IsWindows11()) + { + // Is Windows 11 + forcedTaskBarEdgeText.Add(TaskBarStuckRectangle.TaskBarForcedEdge.Left, "Left"); + forcedTaskBarEdgeText.Add(TaskBarStuckRectangle.TaskBarForcedEdge.Top, "Top"); + forcedTaskBarEdgeText.Add(TaskBarStuckRectangle.TaskBarForcedEdge.Right, "Right"); + forcedTaskBarEdgeText.Add(TaskBarStuckRectangle.TaskBarForcedEdge.Bottom, "Bottom"); + } + else + { + // Is Windows 10 + forcedTaskBarEdgeText.Add(TaskBarStuckRectangle.TaskBarForcedEdge.Left, "Left"); + forcedTaskBarEdgeText.Add(TaskBarStuckRectangle.TaskBarForcedEdge.Top, "Top"); + forcedTaskBarEdgeText.Add(TaskBarStuckRectangle.TaskBarForcedEdge.Right, "Right"); + forcedTaskBarEdgeText.Add(TaskBarStuckRectangle.TaskBarForcedEdge.Bottom, "Bottom"); + } + + cmb_forced_taskbar_location.DisplayMember = "Value"; + cmb_forced_taskbar_location.ValueMember = "Text"; + cmb_forced_taskbar_location.DataSource = new BindingSource(forcedTaskBarEdgeText, null); } public ProfileItem Profile @@ -89,6 +113,18 @@ namespace DisplayMagician.UIForms cmb_wallpaper_display_mode.SelectedIndex = 0; } + + if (Profile.ForcedTaskBarEdge.Equals(TaskBarStuckRectangle.TaskBarForcedEdge.None)) + { + rb_default_taskbar.Checked = true; + cmb_forced_taskbar_location.SelectedIndex = 3; + } + else + { + rb_forced_taskbar.Checked = true; + cmb_forced_taskbar_location.SelectedIndex = cmb_forced_taskbar_location.FindStringExact(forcedTaskBarEdgeText[Profile.ForcedTaskBarEdge]); + } + } private void ProfileSettingsForm_FormClosing(object sender, FormClosingEventArgs e) @@ -107,6 +143,18 @@ namespace DisplayMagician.UIForms } Profile.WallpaperStyle = ((KeyValuePair)cmb_wallpaper_display_mode.SelectedItem).Key; + + if (rb_default_taskbar.Checked) + { + Profile.ForcedTaskBarEdge = TaskBarStuckRectangle.TaskBarForcedEdge.None; + } + else + { + Profile.ForcedTaskBarEdge = ((KeyValuePair)cmb_forced_taskbar_location.SelectedItem).Key; + } + // Apply the changed taskbar settings to the windows config if needed + WINDOWS_DISPLAY_CONFIG winDispConfig = Profile.WindowsDisplayConfig; + TaskBarStuckRectangle.ForceTaskBarIfNeeded(ref winDispConfig.TaskBarLayout, Profile.ForcedTaskBarEdge); } private void btn_back_Click(object sender, EventArgs e) @@ -315,5 +363,30 @@ namespace DisplayMagician.UIForms } } + + private void cmb_forced_taskbar_location_SelectedIndexChanged(object sender, EventArgs e) + { + _profileSettingChanged = true; + } + + private void rb_default_taskbar_CheckedChanged(object sender, EventArgs e) + { + _profileSettingChanged = true; + if (rb_default_taskbar.Checked) + { + // Disable all the things + cmb_forced_taskbar_location.Enabled = false; + } + } + + private void rb_forced_taskbar_CheckedChanged(object sender, EventArgs e) + { + _profileSettingChanged = true; + if (rb_forced_taskbar.Checked) + { + // Disable all the things + cmb_forced_taskbar_location.Enabled = true; + } + } } } diff --git a/DisplayMagicianShared/ProfileItem.cs b/DisplayMagicianShared/ProfileItem.cs index bc9275a..f17fb5b 100644 --- a/DisplayMagicianShared/ProfileItem.cs +++ b/DisplayMagicianShared/ProfileItem.cs @@ -73,6 +73,7 @@ namespace DisplayMagicianShared private bool _isPossible = false; private Keys _hotkey = Keys.None; private string _wallpaperBitmapFilename = ""; + private TaskBarStuckRectangle.TaskBarForcedEdge _forcedTaskBarEdge = TaskBarStuckRectangle.TaskBarForcedEdge.None; #region JsonConverterBitmap @@ -289,6 +290,17 @@ namespace DisplayMagicianShared } public string SavedProfileIconCacheFilename { get; set; } + + public TaskBarStuckRectangle.TaskBarForcedEdge ForcedTaskBarEdge { + get + { + return _forcedTaskBarEdge; + } + set + { + _forcedTaskBarEdge = value; + } + } public Wallpaper.Mode WallpaperMode { get; set; } @@ -449,6 +461,7 @@ namespace DisplayMagicianShared profile.WallpaperMode = WallpaperMode; profile.WallpaperBitmapFilename = WallpaperBitmapFilename; profile.WallpaperStyle = WallpaperStyle; + profile.ForcedTaskBarEdge = ForcedTaskBarEdge; return true; } @@ -672,11 +685,10 @@ namespace DisplayMagicianShared // Lets update the screens so Windows knows whats happening // NVIDIA makes such large changes to the available screens in windows, we need to do this. winLibrary.UpdateActiveConfig(); - - + // Then let's try to also apply the windows changes // Note: we are unable to check if the Windows CCD display config is possible, as it won't match if either the current display config is a Mosaic config, - // or if the display config we want to change to is a Mosaic config. So we just have to assume that it will work! + // or if the display config we want to change to is a Mosaic config. So we just have to assume that it will work bool itWorkedforWindows = winLibrary.SetActiveConfig(_windowsDisplayConfig); if (itWorkedforWindows) { diff --git a/DisplayMagicianShared/ProfileRepository.cs b/DisplayMagicianShared/ProfileRepository.cs index 176e080..656c2c3 100644 --- a/DisplayMagicianShared/ProfileRepository.cs +++ b/DisplayMagicianShared/ProfileRepository.cs @@ -839,7 +839,24 @@ namespace DisplayMagicianShared // We do the actual change we were trying to do try { - + // Now we try to patch in a Windows Taskbar Stuck Rects list into the json if there isnt one + SharedLogger.logger.Trace($"ProfileRepository/MigrateJsonToLatestVersion: Looking for a missing ForcedTaskBarEdge setting in Profile."); + // Create a default object (a default of NONE) + TaskBarStuckRectangle.TaskBarForcedEdge taskBarForcedEdge = TaskBarStuckRectangle.TaskBarForcedEdge.None; + for (int i = 0; i < root.Count; i++) + { + JObject profile = (JObject)root[i]; + JValue forcedTaskBarEdge = (JValue)profile.SelectToken("ForcedTaskBarEdge"); + if (forcedTaskBarEdge == null) + { + JProperty newForcedTaskBarEdge = new JProperty("ForcedTaskBarEdge", TaskBarStuckRectangle.TaskBarForcedEdge.None); + profile.Add("ForcedTaskBarEdge", newForcedTaskBarEdge); + changedJson = true; + SharedLogger.logger.Trace($"ProfileRepository/MigrateJsonToLatestVersion: Patched missing ForcedTaskBarEdge in profile {profile.SelectToken("Name")} (index {i})."); + } + } + + // Now we try to patch in a Windows Taskbar Stuck Rects list into the json if there isnt one SharedLogger.logger.Trace($"ProfileRepository/MigrateJsonToLatestVersion: Looking for missing Windows Taskbar layout."); // Create a default object (an empty list) @@ -879,11 +896,11 @@ namespace DisplayMagicianShared } catch (JsonReaderException ex) { - SharedLogger.logger.Error($"ProfileRepository/MigrateJsonToLatestVersion: JSONReaderException while trying to process the Profiles json data to migrate any older feature to the latest version."); + SharedLogger.logger.Error(ex, $"ProfileRepository/MigrateJsonToLatestVersion: JSONReaderException while trying to process the Profiles json data to migrate any older feature to the latest version."); } catch (Exception ex) { - SharedLogger.logger.Error($"ProfileRepository/MigrateJsonToLatestVersion: Exception while trying to process the Profiles json data to migrate any older feature to the latest version."); + SharedLogger.logger.Error(ex, $"ProfileRepository/MigrateJsonToLatestVersion: Exception while trying to process the Profiles json data to migrate any older feature to the latest version."); } // Now write the changed json to the json string but only if we've changed something diff --git a/DisplayMagicianShared/RestartManagerSession.cs b/DisplayMagicianShared/RestartManagerSession.cs index 45bd8fe..12ab087 100644 --- a/DisplayMagicianShared/RestartManagerSession.cs +++ b/DisplayMagicianShared/RestartManagerSession.cs @@ -300,7 +300,7 @@ namespace DisplayMagicianShared RestartManagerSession restartManager = new RestartManagerSession(); FileInfo explorerFileInfo = new FileInfo(@"C:\Windows\explorer.exe"); restartManager.RegisterProcessFile(explorerFileInfo); - restartManager.Shutdown(RestartManagerSession.ShutdownType.ForceShutdown); + restartManager.Shutdown(RestartManagerSession.ShutdownType.Normal); restartManager.Restart(); restartManager.Dispose(); return true; diff --git a/DisplayMagicianShared/Utils.cs b/DisplayMagicianShared/Utils.cs index a9e8f9f..289d44a 100644 --- a/DisplayMagicianShared/Utils.cs +++ b/DisplayMagicianShared/Utils.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; @@ -18,5 +19,25 @@ namespace DisplayMagicianShared return currentBuild >= 22000; } + + [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] + public static extern IntPtr SendMessageTimeout(IntPtr windowHandle, uint message, IntPtr wordParameter, IntPtr longParameter, SendMessageTimeoutFlag flag, uint timeout, out IntPtr resultHandle); + + [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)] + public static extern bool SendNotifyMessage(IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam); + + [Flags] + public enum SendMessageTimeoutFlag : uint + { + SMTO_NORMAL = 0x0, + SMTO_BLOCK = 0x1, + SMTO_ABORTIFHUNG = 0x2, + SMTO_NOTIMEOUTIFNOTHUNG = 0x8, + SMTO_ERRORONEXIT = 0x20 + } + + public const int NULL = 0; + public const int HWND_BROADCAST = 0xffff; + public const int WM_SETTINGCHANGE = 0x001a; } } diff --git a/DisplayMagicianShared/Windows/TaskBarStuckRectangle.cs b/DisplayMagicianShared/Windows/TaskBarStuckRectangle.cs index 4a96b2e..9f1043b 100644 --- a/DisplayMagicianShared/Windows/TaskBarStuckRectangle.cs +++ b/DisplayMagicianShared/Windows/TaskBarStuckRectangle.cs @@ -2,7 +2,8 @@ using System.Collections.Generic; using System.Drawing; using System.Text.RegularExpressions; -using DisplayMagicianShared.Windows; +using System.Threading.Tasks; +using DisplayMagicianShared; using Microsoft.Win32; using Newtonsoft.Json; @@ -15,6 +16,15 @@ namespace DisplayMagicianShared.Windows { public class TaskBarStuckRectangle { + public enum TaskBarForcedEdge : UInt32 + { + Left = 0, + Top = 1, + Right = 2, + Bottom = 3, + None = 9999 + } + public enum TaskBarEdge : UInt32 { Left = 0, @@ -87,6 +97,8 @@ namespace DisplayMagicianShared.Windows public byte[] Binary { get; set; } + public byte[] BinaryBackup { get; set; } + public string DevicePath { get; set; } public bool MainScreen { get; set; } @@ -259,16 +271,23 @@ namespace DisplayMagicianShared.Windows public override bool Equals(object obj) => obj is TaskBarStuckRectangle other && this.Equals(other); public bool Equals(TaskBarStuckRectangle other) - => Version == other.Version && - MainScreen == other.MainScreen && - DevicePath == other.DevicePath && - Xor(Binary, other.Binary); + { + // We return all the fields + return Version == other.Version && + MainScreen == other.MainScreen && + DevicePath == other.DevicePath && + Edge == other.Edge && + Location == other.Location; + // && + //Xor(Binary, other.Binary); + } + public override int GetHashCode() { - //return (DisplayConfigPaths, DisplayConfigModes, DisplayHDRStates, GdiDisplaySettings.Values, IsCloned, DisplayIdentifiers).GetHashCode(); - return (Version, MainScreen, DevicePath, Binary).GetHashCode(); + //return (Version, MainScreen, DevicePath, Binary).GetHashCode(); + return (Version, MainScreen, DevicePath, Edge, Location).GetHashCode(); } public static bool operator ==(TaskBarStuckRectangle lhs, TaskBarStuckRectangle rhs) => lhs.Equals(rhs); @@ -292,80 +311,13 @@ namespace DisplayMagicianShared.Windows } - /*public static TaskBarStuckRectangle GetCurrent() - { - return GetCurrent((string)null); - }*/ - - /*public static TaskBarStuckRectangle GetCurrent(PathDisplayTarget pathTargetInfo) - { - var devicePath = pathTargetInfo?.DevicePath; - var index = devicePath?.IndexOf("{", StringComparison.InvariantCultureIgnoreCase); - - if (index > 0) - { - devicePath = devicePath.Substring(0, index.Value).TrimEnd('#'); - } - - index = devicePath?.IndexOf("#", StringComparison.InvariantCultureIgnoreCase); - - if (index > 0) - { - devicePath = devicePath.Substring(index.Value).TrimStart('#'); - } - - return GetCurrent(devicePath); - }*/ public static List GetCurrent(List displayIdentifiers) { List taskBarStuckRectangles = new List(); int version = 2; - var address = string.Format(MainDisplayAddress, version); - if (Registry.CurrentUser.OpenSubKey(address) == null) - { - // If it's not version 2, then try version 3 - version = 3; - address = string.Format(MainDisplayAddress, version); - if (Registry.CurrentUser.OpenSubKey(address) == null) - { - // It's not v2 or v3, so error - version = -1; - } - } - - if (version >= 2) - { - // Grab the main screen taskbar placement - try - { - using (var key = Registry.CurrentUser.OpenSubKey( - address, - RegistryKeyPermissionCheck.ReadSubTree)) - { - var settings = key?.GetValue("Settings") as byte[]; - - if (settings?.Length > 0) - { - TaskBarStuckRectangle taskBarStuckRectangle = new TaskBarStuckRectangle - { - MainScreen = true, - DevicePath = "Settings", - Binary = settings, - Version = version - }; - taskBarStuckRectangles.Add(taskBarStuckRectangle); - } - } - } - catch (Exception ex) - { - SharedLogger.logger.Error(ex, $"TaskBarStuckRectangle/GetCurrent: Unable to read the Main Screen TaskBarStuckRectangle registry settings due to an exception!"); - } - } - - version = 2; + string address = ""; address = string.Format(MultiDisplayAddress, version); if (Registry.CurrentUser.OpenSubKey(address) == null) { @@ -396,7 +348,6 @@ namespace DisplayMagicianShared.Windows RegistryKeyPermissionCheck.ReadSubTree)) { var settings = key?.GetValue(tbStuckRectKey) as byte[]; - if (settings?.Length > 0) { taskBarStuckRectangle = new TaskBarStuckRectangle @@ -404,6 +355,7 @@ namespace DisplayMagicianShared.Windows MainScreen = false, DevicePath = tbStuckRectKey, Binary = settings, + BinaryBackup = settings, Version = version }; taskBarStuckRectangles.Add(taskBarStuckRectangle); @@ -413,7 +365,7 @@ namespace DisplayMagicianShared.Windows { SharedLogger.logger.Trace($"WinLibrary/GetWindowsDisplayConfig: Unable to get the TaskBarStuckRectangle for {displayId}."); } - } + } } else { @@ -422,43 +374,100 @@ namespace DisplayMagicianShared.Windows } } + version = 2; + address = string.Format(MainDisplayAddress, version); + if (Registry.CurrentUser.OpenSubKey(address) == null) + { + // If it's not version 2, then try version 3 + version = 3; + address = string.Format(MainDisplayAddress, version); + if (Registry.CurrentUser.OpenSubKey(address) == null) + { + // It's not v2 or v3, so error + version = -1; + } + } + + if (version >= 2) + { + // Grab the main screen taskbar placement + try + { + using (var key = Registry.CurrentUser.OpenSubKey( + address, + RegistryKeyPermissionCheck.ReadSubTree)) + { + var settings = key?.GetValue("Settings") as byte[]; + + if (settings?.Length > 0) + { + TaskBarStuckRectangle taskBarStuckRectangle = new TaskBarStuckRectangle + { + MainScreen = true, + DevicePath = "Settings", + Binary = settings, + BinaryBackup = settings, + Version = version + }; + taskBarStuckRectangles.Add(taskBarStuckRectangle); + } + } + } + catch (Exception ex) + { + SharedLogger.logger.Error(ex, $"TaskBarStuckRectangle/GetCurrent: Unable to read the Main Screen TaskBarStuckRectangle registry settings due to an exception!"); + } + } + + return taskBarStuckRectangles; } - public static bool Apply(List taskBarStuckRectangles) + public static bool ForceTaskBarIfNeeded(ref List taskBarStuckRectangles, TaskBarForcedEdge forcedEdge = TaskBarForcedEdge.None) { - if (taskBarStuckRectangles.Count == 0) + try + { + if (forcedEdge != TaskBarForcedEdge.None) + { + for (int i = 0; i < taskBarStuckRectangles.Count; i++) + { + // Force the taskbar change + taskBarStuckRectangles[i].Edge = (TaskBarEdge)forcedEdge; + taskBarStuckRectangles[i].Location = Rectangle.Empty; + } + } + else if (forcedEdge == TaskBarForcedEdge.None) + { + // Revert the forced taskbar change from the backup + for (int i = 0; i < taskBarStuckRectangles.Count; i++) + { + taskBarStuckRectangles[i].Binary = taskBarStuckRectangles[i].BinaryBackup; + } + } + return true; + } + catch (Exception ex) { return false; } + } + + public static bool Apply(List taskBarStuckRectangles, TaskBarForcedEdge forcedEdge = TaskBarForcedEdge.None) + { string address; + if (taskBarStuckRectangles.Count < 1) + { + SharedLogger.logger.Trace($"TaskBarStuckRectangle/Apply: There are no TaskBarStuckRectangle registry settings to apply! This taskbar configuration is invalid."); + return false; + } foreach (TaskBarStuckRectangle tbsr in taskBarStuckRectangles) { if (tbsr.Version >= 2 && tbsr.Version <= 3) { - if (tbsr.MainScreen) - { - address = string.Format(MainDisplayAddress, tbsr.Version); - // Grab the main screen taskbar placement - try - { - using (var key = Registry.CurrentUser.OpenSubKey( - address, - RegistryKeyPermissionCheck.ReadWriteSubTree)) - { - key.SetValue("Settings", tbsr.Binary); - SharedLogger.logger.Trace($"TaskBarStuckRectangle/Apply: Successfully applied TaskBarStuckRectangle registry settings for the Main Screen!"); - } - } - catch (Exception ex) - { - SharedLogger.logger.Error(ex, $"TaskBarStuckRectangle/GetCurrent: Unable to set the Main Screen TaskBarStuckRectangle registry settings due to an exception!"); - } - } - else + if (!tbsr.MainScreen) { address = string.Format(MultiDisplayAddress, tbsr.Version); // Grab the main screen taskbar placement @@ -473,6 +482,40 @@ namespace DisplayMagicianShared.Windows } } catch (Exception ex) + { + SharedLogger.logger.Error(ex, $"TaskBarStuckRectangle/GetCurrent: Unable to set the {tbsr.DevicePath} TaskBarStuckRectangle registry settings due to an exception!"); + } + } + } + else + { + SharedLogger.logger.Error($"TaskBarStuckRectangle/GetCurrent: Unable to set the {tbsr.DevicePath} TaskBarStuckRectangle registry settings as the version isn't v2 or v3!"); + } + } + + // Tell Windows to refresh the Windows Taskbar (which will only refresh the non-main screen) + Utils.SendNotifyMessage((IntPtr)Utils.HWND_BROADCAST, Utils.WM_SETTINGCHANGE, (UIntPtr)Utils.NULL, "TraySettings"); + + foreach (TaskBarStuckRectangle tbsr in taskBarStuckRectangles) + { + if (tbsr.Version >= 2 && tbsr.Version <= 3) + { + if (tbsr.MainScreen) + { + + address = string.Format(MainDisplayAddress, tbsr.Version); + // Grab the main screen taskbar placement + try + { + using (var key2 = Registry.CurrentUser.OpenSubKey( + address, + RegistryKeyPermissionCheck.ReadWriteSubTree)) + { + key2.SetValue("Settings", tbsr.Binary); + SharedLogger.logger.Trace($"TaskBarStuckRectangle/Apply: Successfully applied TaskBarStuckRectangle registry settings for the Main Screen!"); + } + } + catch (Exception ex) { SharedLogger.logger.Error(ex, $"TaskBarStuckRectangle/GetCurrent: Unable to set the Main Screen TaskBarStuckRectangle registry settings due to an exception!"); } @@ -480,10 +523,18 @@ namespace DisplayMagicianShared.Windows } else { - SharedLogger.logger.Error($"TaskBarStuckRectangle/GetCurrent: Unable to set the Main Screen TaskBarStuckRectangle registry settings due to an exception!"); + SharedLogger.logger.Error($"TaskBarStuckRectangle/GetCurrent: Unable to set the Main Screen TaskBarStuckRectangle registry settings as the version isn't v2 or v3!"); } } + // Tell Windows to refresh the Windows Taskbar (which will only refresh the non-main screen) + Utils.SendNotifyMessage((IntPtr)Utils.HWND_BROADCAST, Utils.WM_SETTINGCHANGE, (UIntPtr)Utils.NULL, "TraySettings"); + + Task.Delay(2000); + + // This will refresh the main screen as well. No idea why the above notification doesn't update the main screen too :/) + //RestartManagerSession.RestartExplorer(); + return true; } }