From 59af249b4a2164cf5172f5110e9e82021960f739 Mon Sep 17 00:00:00 2001 From: Adam Kauffman Date: Mon, 11 May 2020 01:52:20 -0700 Subject: [PATCH 1/4] ReSharpened Run ReSharper Code Cleanup Run Optimize References Close All Sensible ReSharper Issues --- CenterTaskbar/CenterTaskbar.csproj | 5 - CenterTaskbar/DisplaySettings.cs | 44 ++- CenterTaskbar/Program.cs | 453 +++++++++++++++-------------- 3 files changed, 249 insertions(+), 253 deletions(-) diff --git a/CenterTaskbar/CenterTaskbar.csproj b/CenterTaskbar/CenterTaskbar.csproj index a748f65..cf0d4b5 100644 --- a/CenterTaskbar/CenterTaskbar.csproj +++ b/CenterTaskbar/CenterTaskbar.csproj @@ -76,13 +76,8 @@ - - - - - diff --git a/CenterTaskbar/DisplaySettings.cs b/CenterTaskbar/DisplaySettings.cs index 970d26c..dc9c936 100644 --- a/CenterTaskbar/DisplaySettings.cs +++ b/CenterTaskbar/DisplaySettings.cs @@ -1,16 +1,15 @@ -using System; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; using System.Windows.Forms; namespace CenterTaskbar { - static class DisplaySettings + internal static class DisplaySettings { [DllImport("user32.dll")] private static extern bool EnumDisplaySettings(string deviceName, int modeNum, ref DEVMODE devMode); const int ENUM_CURRENT_SETTINGS = -1; - //const int ENUM_REGISTRY_SETTINGS = -2; + const int ENUM_REGISTRY_SETTINGS = -2; [StructLayout(LayoutKind.Sequential)] private struct DEVMODE @@ -53,30 +52,25 @@ private struct DEVMODE } - public static void ListAllDisplayModes() - { - DEVMODE vDevMode = new DEVMODE(); - int i = 0; - while (EnumDisplaySettings(null, i, ref vDevMode)) - { - Console.WriteLine("Width:{0} Height:{1} Color:{2} Frequency:{3}", - vDevMode.dmPelsWidth, - vDevMode.dmPelsHeight, - 1 << vDevMode.dmBitsPerPel, vDevMode.dmDisplayFrequency - ); - i++; - } - } + //public static void ListAllDisplayModes() + //{ + // DEVMODE vDevMode = new DEVMODE(); + // int i = 0; + // while (EnumDisplaySettings(null, i, ref vDevMode)) + // { + // Console.WriteLine("Width:{0} Height:{1} Color:{2} Frequency:{3}", + // vDevMode.dmPelsWidth, + // vDevMode.dmPelsHeight, + // 1 << vDevMode.dmBitsPerPel, vDevMode.dmDisplayFrequency + // ); + // i++; + // } + //} public static int CurrentRefreshRate() { - DEVMODE vDevMode = new DEVMODE(); - if (EnumDisplaySettings(null, ENUM_CURRENT_SETTINGS, ref vDevMode)) { - return vDevMode.dmDisplayFrequency; - } else - { - return 60; - } + var vDevMode = new DEVMODE(); + return EnumDisplaySettings(null, ENUM_CURRENT_SETTINGS, ref vDevMode) ? vDevMode.dmDisplayFrequency : 60; } } } diff --git a/CenterTaskbar/Program.cs b/CenterTaskbar/Program.cs index 59f3495..d2378eb 100644 --- a/CenterTaskbar/Program.cs +++ b/CenterTaskbar/Program.cs @@ -1,31 +1,33 @@ using System; -using System.Windows; -using System.Windows.Forms; -using System.Windows.Automation; -using Microsoft.Win32; -using System.Runtime.InteropServices; -using System.Diagnostics; -using System.Threading; using System.Collections.Generic; +using System.Diagnostics; using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Automation; +using System.Windows.Forms; +using CenterTaskbar.Properties; +using Microsoft.Win32; namespace CenterTaskbar { - static class Program + internal static class Program { /// /// The main entry point for the application. /// [STAThread] - static void Main(string[] args) + private static void Main(string[] args) { // Only allow one instance of this application to run at a time using GUID - string assyGuid = Assembly.GetExecutingAssembly().GetCustomAttribute().Value.ToUpper(); - using (Mutex mutex = new Mutex(true, assyGuid, out bool firstInstance)) + var assyGuid = Assembly.GetExecutingAssembly().GetCustomAttribute().Value.ToUpper(); + using (new Mutex(true, assyGuid, out var firstInstance)) { if (!firstInstance) { - MessageBox.Show("Another instance is already running.", "CenterTaskbar", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + MessageBox.Show("Another instance is already running.", "CenterTaskbar", MessageBoxButtons.OK, + MessageBoxIcon.Exclamation); return; } @@ -38,65 +40,70 @@ static void Main(string[] args) public class TrayApplication : ApplicationContext { - private const String appName = "CenterTaskbar"; - private const String runRegkey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"; + private const string AppName = "CenterTaskbar"; + private const string RunRegkey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"; private const int SWP_NOSIZE = 0x0001; + private const int SWP_NOZORDER = 0x0004; + //private const int SWP_SHOWWINDOW = 0x0040; private const int SWP_ASYNCWINDOWPOS = 0x4000; - private const String MSTaskListWClass = "MSTaskListWClass"; + + private const string MSTaskListWClass = "MSTaskListWClass"; + //private const String ReBarWindow32 = "ReBarWindow32"; - private const String Shell_TrayWnd = "Shell_TrayWnd"; - private const String Shell_SecondaryTrayWnd = "Shell_SecondaryTrayWnd"; - private static readonly String ExecutablePath = "\"" + Application.ExecutablePath + "\""; + private const string ShellTrayWnd = "Shell_TrayWnd"; + private const string ShellSecondaryTrayWnd = "Shell_SecondaryTrayWnd"; + private static readonly string ExecutablePath = "\"" + Application.ExecutablePath + "\""; - private static bool disposed = false; + private static bool _disposed; + private static readonly AutomationElement Desktop = AutomationElement.RootElement; + private static AutomationEventHandler _uiaEventHandler; + private static AutomationPropertyChangedEventHandler _propChangeHandler; - private readonly NotifyIcon trayIcon; - private static readonly AutomationElement desktop = AutomationElement.RootElement; - private static AutomationEventHandler UIAeventHandler; - private static AutomationPropertyChangedEventHandler propChangeHandler; - private readonly Dictionary lasts = new Dictionary(); - private readonly Dictionary children = new Dictionary(); - private readonly List bars = new List(); + private readonly int _activeFramerate = DisplaySettings.CurrentRefreshRate(); + private readonly List _bars = new List(); - private readonly int activeFramerate = DisplaySettings.CurrentRefreshRate(); - // private Thread positionThread; - private Dictionary positionThreads = new Dictionary(); + private readonly Dictionary _children = + new Dictionary(); - [DllImport("user32.dll", SetLastError = true)] - private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags); + private readonly Dictionary _lasts = new Dictionary(); + + private readonly NotifyIcon _trayIcon; + + // private Thread positionThread; + private readonly Dictionary _positionThreads = + new Dictionary(); public TrayApplication(string[] args) { if (args.Length > 0) - { try { - activeFramerate = Int32.Parse(args[0]); - Debug.WriteLine("Active refresh rate: " + activeFramerate); + _activeFramerate = int.Parse(args[0]); + Debug.WriteLine("Active refresh rate: " + _activeFramerate); } catch (FormatException e) { - Debug.WriteLine(e.Message); + Debug.WriteLine(e.Message); } - } - MenuItem header = new MenuItem("CenterTaskbar (" + activeFramerate + ")", Exit) + var header = new MenuItem("CenterTaskbar (" + _activeFramerate + ")", Exit) { Enabled = false }; - MenuItem startup = new MenuItem("Start with Windows", ToggleStartup) + var startup = new MenuItem("Start with Windows", ToggleStartup) { - Checked = IsApplicationInStatup() + Checked = IsApplicationInStartup() }; // Setup Tray Icon - trayIcon = new NotifyIcon() + _trayIcon = new NotifyIcon { - Icon = Properties.Resources.TrayIcon, - ContextMenu = new ContextMenu(new MenuItem[] { + Icon = Resources.TrayIcon, + ContextMenu = new ContextMenu(new[] + { header, new MenuItem("Scan for screens", Restart), startup, @@ -108,66 +115,59 @@ public TrayApplication(string[] args) Start(); } + [DllImport("user32.dll", SetLastError = true)] + private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, int uFlags); + public void ToggleStartup(object sender, EventArgs e) { - if (IsApplicationInStatup()) + if (IsApplicationInStartup()) { RemoveApplicationFromStartup(); - (sender as MenuItem).Checked = false; - } else + ((MenuItem) sender).Checked = false; + } + else { AddApplicationToStartup(); - (sender as MenuItem).Checked = true; + ((MenuItem) sender).Checked = true; } } - public bool IsApplicationInStatup() + public bool IsApplicationInStartup() { - using (RegistryKey key = Registry.CurrentUser.OpenSubKey(runRegkey, true)) + using (var key = Registry.CurrentUser.OpenSubKey(RunRegkey, true)) { - if (key == null) return false; - - object value = key.GetValue(appName); - if (value is String) - { - ; - return ((value as String).StartsWith(ExecutablePath)); - } - - return false; + var value = key?.GetValue(AppName); + return value is string startValue && startValue.StartsWith(ExecutablePath); } } public void AddApplicationToStartup() { - using (RegistryKey key = Registry.CurrentUser.OpenSubKey(runRegkey, true)) + using (var key = Registry.CurrentUser.OpenSubKey(RunRegkey, true)) { - key.SetValue(appName, ExecutablePath); + key?.SetValue(AppName, ExecutablePath); } } public void RemoveApplicationFromStartup() { - using (RegistryKey key = Registry.CurrentUser.OpenSubKey(runRegkey, true)) + using (var key = Registry.CurrentUser.OpenSubKey(RunRegkey, true)) { - key.DeleteValue(appName, false); + key?.DeleteValue(AppName, false); } } - void Exit(object sender, EventArgs e) + private static void Exit(object sender, EventArgs e) { Application.ExitThread(); } private void CancelPositionThread() { - foreach (Thread thread in positionThreads.Values) - { - thread.Abort(); - } + foreach (var thread in _positionThreads.Values) thread.Abort(); } - void Restart(object sender, EventArgs e) + private void Restart(object sender, EventArgs e) { CancelPositionThread(); Start(); @@ -176,49 +176,48 @@ void Restart(object sender, EventArgs e) private void ResetAll() { CancelPositionThread(); - foreach (AutomationElement trayWnd in bars) - { - Reset(trayWnd); - } + foreach (var trayWnd in _bars) Reset(trayWnd); } - private void Reset(AutomationElement trayWnd) + private static void Reset(AutomationElement trayWnd) { Debug.WriteLine("Begin Reset Calculation"); - AutomationElement tasklist = trayWnd.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ClassNameProperty, MSTaskListWClass)); + var tasklist = trayWnd.FindFirst(TreeScope.Descendants, + new PropertyCondition(AutomationElement.ClassNameProperty, MSTaskListWClass)); if (tasklist == null) { Debug.WriteLine("Null values found, aborting reset"); return; } - AutomationElement tasklistcontainer = TreeWalker.ControlViewWalker.GetParent(tasklist); + var tasklistcontainer = TreeWalker.ControlViewWalker.GetParent(tasklist); if (tasklistcontainer == null) { Debug.WriteLine("Null values found, aborting reset"); return; } - IntPtr tasklistPtr = (IntPtr)tasklist.Current.NativeWindowHandle; - + var tasklistPtr = (IntPtr) tasklist.Current.NativeWindowHandle; + SetWindowPos(tasklistPtr, IntPtr.Zero, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_ASYNCWINDOWPOS); } private void Start() { - OrCondition condition = new OrCondition(new PropertyCondition(AutomationElement.ClassNameProperty, Shell_TrayWnd), new PropertyCondition(AutomationElement.ClassNameProperty, Shell_SecondaryTrayWnd)); - CacheRequest cacheRequest = new CacheRequest(); + var condition = new OrCondition(new PropertyCondition(AutomationElement.ClassNameProperty, ShellTrayWnd), + new PropertyCondition(AutomationElement.ClassNameProperty, ShellSecondaryTrayWnd)); + var cacheRequest = new CacheRequest(); cacheRequest.Add(AutomationElement.NameProperty); cacheRequest.Add(AutomationElement.BoundingRectangleProperty); - bars.Clear(); - children.Clear(); - lasts.Clear(); + _bars.Clear(); + _children.Clear(); + _lasts.Clear(); using (cacheRequest.Activate()) { - AutomationElementCollection lists = desktop.FindAll(TreeScope.Children, condition); + var lists = Desktop.FindAll(TreeScope.Children, condition); if (lists == null) { Debug.WriteLine("Null values found, aborting"); @@ -226,61 +225,60 @@ private void Start() } Debug.WriteLine(lists.Count + " bar(s) detected"); - lasts.Clear(); + _lasts.Clear(); foreach (AutomationElement trayWnd in lists) { - AutomationElement tasklist = trayWnd.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ClassNameProperty, MSTaskListWClass)); + var tasklist = trayWnd.FindFirst(TreeScope.Descendants, + new PropertyCondition(AutomationElement.ClassNameProperty, MSTaskListWClass)); if (tasklist == null) { Debug.WriteLine("Null values found, aborting"); continue; } - propChangeHandler = new AutomationPropertyChangedEventHandler(OnUIAutomationEvent); - Automation.AddAutomationPropertyChangedEventHandler(tasklist, TreeScope.Element, propChangeHandler, AutomationElement.BoundingRectangleProperty); + _propChangeHandler = OnUIAutomationEvent; + Automation.AddAutomationPropertyChangedEventHandler(tasklist, TreeScope.Element, _propChangeHandler, + AutomationElement.BoundingRectangleProperty); - bars.Add(trayWnd); - children.Add(trayWnd, tasklist); - positionThreads[trayWnd] = new Thread(new ParameterizedThreadStart(LoopForPosition)); - positionThreads[trayWnd].Start(trayWnd); + _bars.Add(trayWnd); + _children.Add(trayWnd, tasklist); + _positionThreads[trayWnd] = new Thread(LoopForPosition); + _positionThreads[trayWnd].Start(trayWnd); } } - UIAeventHandler = new AutomationEventHandler(OnUIAutomationEvent); - Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent, desktop, TreeScope.Subtree, UIAeventHandler); - Automation.AddAutomationEventHandler(WindowPattern.WindowClosedEvent, desktop, TreeScope.Subtree, UIAeventHandler); + _uiaEventHandler = OnUIAutomationEvent; + Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent, Desktop, TreeScope.Subtree, + _uiaEventHandler); + Automation.AddAutomationEventHandler(WindowPattern.WindowClosedEvent, Desktop, TreeScope.Subtree, + _uiaEventHandler); } private void OnUIAutomationEvent(object src, AutomationEventArgs e) { Debug.Print("Event occured: {0}", e.EventId.ProgrammaticName); - foreach (AutomationElement trayWnd in bars) - { - if (!positionThreads[trayWnd].IsAlive) + foreach (var trayWnd in _bars) + if (!_positionThreads[trayWnd].IsAlive) { Debug.WriteLine("Starting new thead"); - positionThreads[trayWnd] = new Thread(new ParameterizedThreadStart(LoopForPosition)); - positionThreads[trayWnd].Start(trayWnd); - } else + _positionThreads[trayWnd] = new Thread(LoopForPosition); + _positionThreads[trayWnd].Start(trayWnd); + } + else { Debug.WriteLine("Thread already exists"); } - } - } private void LoopForPosition(object trayWndObj) { - AutomationElement trayWnd = (AutomationElement)trayWndObj; - int numberOfLoops = activeFramerate / 10; - int keepGoing = 0; + var trayWnd = (AutomationElement) trayWndObj; + var numberOfLoops = _activeFramerate / 10; + var keepGoing = 0; while (keepGoing < numberOfLoops) { - if (!PositionLoop(trayWnd)) - { - keepGoing += 1; - } - System.Threading.Tasks.Task.Delay(1000 / activeFramerate).Wait(); + if (!PositionLoop(trayWnd)) keepGoing += 1; + Task.Delay(1000 / _activeFramerate).Wait(); } Debug.WriteLine("LoopForPosition Thread ended."); @@ -290,123 +288,134 @@ private bool PositionLoop(AutomationElement trayWnd) { Debug.WriteLine("Begin Reposition Calculation"); - AutomationElement tasklist = children[trayWnd]; - AutomationElement last = TreeWalker.ControlViewWalker.GetLastChild(tasklist); + var tasklist = _children[trayWnd]; + var last = TreeWalker.ControlViewWalker.GetLastChild(tasklist); if (last == null) { Debug.WriteLine("Null values found for items, aborting"); return true; } - Rect trayBounds = trayWnd.Cached.BoundingRectangle; - bool horizontal = trayBounds.Width > trayBounds.Height; + var trayBounds = trayWnd.Cached.BoundingRectangle; + var horizontal = trayBounds.Width > trayBounds.Height; // Use the left/top bounds because there is an empty element as the last child with a nonzero width - double lastChildPos = horizontal ? last.Current.BoundingRectangle.Left : last.Current.BoundingRectangle.Top; + var lastChildPos = horizontal ? last.Current.BoundingRectangle.Left : last.Current.BoundingRectangle.Top; Debug.WriteLine("Last child position: " + lastChildPos); - if (lasts.ContainsKey(trayWnd) && lastChildPos == lasts[trayWnd]) + if (_lasts.ContainsKey(trayWnd) && lastChildPos == _lasts[trayWnd]) { Debug.WriteLine("Size/location unchanged, sleeping"); return false; - } else - { - Debug.WriteLine("Size/location changed, recalculating center"); - lasts[trayWnd] = lastChildPos; + } - AutomationElement first = TreeWalker.ControlViewWalker.GetFirstChild(tasklist); - if (first == null) - { - Debug.WriteLine("Null values found for first child item, aborting"); - return true; - } + Debug.WriteLine("Size/location changed, recalculating center"); + _lasts[trayWnd] = lastChildPos; - double scale = horizontal ? (last.Current.BoundingRectangle.Height / trayBounds.Height) : (last.Current.BoundingRectangle.Width / trayBounds.Width); - Debug.WriteLine("UI Scale: " + scale); - double size = (lastChildPos - (horizontal ? first.Current.BoundingRectangle.Left : first.Current.BoundingRectangle.Top)) / scale; - if (size < 0) - { - Debug.WriteLine("Size calculation failed"); - return true; - } - - AutomationElement tasklistcontainer = TreeWalker.ControlViewWalker.GetParent(tasklist); - if (tasklistcontainer == null) - { - Debug.WriteLine("Null values found for parent, aborting"); - return true; - } + var first = TreeWalker.ControlViewWalker.GetFirstChild(tasklist); + if (first == null) + { + Debug.WriteLine("Null values found for first child item, aborting"); + return true; + } - Rect tasklistBounds = tasklist.Current.BoundingRectangle; + var scale = horizontal + ? last.Current.BoundingRectangle.Height / trayBounds.Height + : last.Current.BoundingRectangle.Width / trayBounds.Width; + Debug.WriteLine("UI Scale: " + scale); + var size = (lastChildPos - + (horizontal ? first.Current.BoundingRectangle.Left : first.Current.BoundingRectangle.Top)) / + scale; + if (size < 0) + { + Debug.WriteLine("Size calculation failed"); + return true; + } - double barSize = horizontal ? trayWnd.Cached.BoundingRectangle.Width : trayWnd.Cached.BoundingRectangle.Height; - double targetPos = Math.Round((barSize - size) / 2) + (horizontal ? trayBounds.X : trayBounds.Y); + var tasklistcontainer = TreeWalker.ControlViewWalker.GetParent(tasklist); + if (tasklistcontainer == null) + { + Debug.WriteLine("Null values found for parent, aborting"); + return true; + } - Debug.Write("Bar size: "); - Debug.WriteLine(barSize); - Debug.Write("Total icon size: "); - Debug.WriteLine(size); - Debug.Write("Target abs " + (horizontal ? "X":"Y") + " position: "); - Debug.WriteLine(targetPos); + var tasklistBounds = tasklist.Current.BoundingRectangle; - double delta = Math.Abs(targetPos - (horizontal ? tasklistBounds.X : tasklistBounds.Y)); - // Previous bounds check - if (delta <= 1) - { - // Already positioned within margin of error, avoid the unneeded MoveWindow call - Debug.WriteLine("Already positioned, ending to avoid the unneeded MoveWindow call (Delta: " + delta + ")"); - return false; - } + var barSize = horizontal ? trayWnd.Cached.BoundingRectangle.Width : trayWnd.Cached.BoundingRectangle.Height; + var targetPos = Math.Round((barSize - size) / 2) + (horizontal ? trayBounds.X : trayBounds.Y); - // Right bounds check - int rightBounds = SideBoundary(false, horizontal, tasklist); - if ((targetPos + size) > rightBounds) - { - // Shift off center when the bar is too big - double extra = (targetPos + size) - rightBounds; - Debug.WriteLine("Shifting off center, too big and hitting right/bottom boundary (" + (targetPos + size) + " > " + rightBounds + ") // " + extra); - targetPos -= extra; - } + Debug.Write("Bar size: "); + Debug.WriteLine(barSize); + Debug.Write("Total icon size: "); + Debug.WriteLine(size); + Debug.Write("Target abs " + (horizontal ? "X" : "Y") + " position: "); + Debug.WriteLine(targetPos); - // Left bounds check - int leftBounds = SideBoundary(true, horizontal, tasklist); - if (targetPos <= leftBounds) - { - // Prevent X position ending up beyond the normal left aligned position - Debug.WriteLine("Target is more left than left/top aligned default, left/top aligning (" + targetPos + " <= " + leftBounds + ")"); - Reset(trayWnd); - return true; - } + var delta = Math.Abs(targetPos - (horizontal ? tasklistBounds.X : tasklistBounds.Y)); + // Previous bounds check + if (delta <= 1) + { + // Already positioned within margin of error, avoid the unneeded MoveWindow call + Debug.WriteLine("Already positioned, ending to avoid the unneeded MoveWindow call (Delta: " + delta + + ")"); + return false; + } - IntPtr tasklistPtr = (IntPtr)tasklist.Current.NativeWindowHandle; + // Right bounds check + var rightBounds = SideBoundary(false, horizontal, tasklist); + if (targetPos + size > rightBounds) + { + // Shift off center when the bar is too big + var extra = targetPos + size - rightBounds; + Debug.WriteLine("Shifting off center, too big and hitting right/bottom boundary (" + + (targetPos + size) + " > " + rightBounds + ") // " + extra); + targetPos -= extra; + } - if (horizontal) - { - SetWindowPos(tasklistPtr, IntPtr.Zero, (RelativePos(targetPos, horizontal, tasklist)), 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_ASYNCWINDOWPOS); - Debug.Write("Final X Position: "); - Debug.WriteLine(tasklist.Current.BoundingRectangle.X); - Debug.Write((tasklist.Current.BoundingRectangle.X == targetPos) ? "Move hit target" : "Move missed target"); - Debug.WriteLine(" (diff: " + Math.Abs(tasklist.Current.BoundingRectangle.X - targetPos) + ")"); - } else - { - SetWindowPos(tasklistPtr, IntPtr.Zero, 0, (RelativePos(targetPos, horizontal, tasklist)), 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_ASYNCWINDOWPOS); - Debug.Write("Final Y Position: "); - Debug.WriteLine(tasklist.Current.BoundingRectangle.Y); - Debug.Write((tasklist.Current.BoundingRectangle.Y == targetPos) ? "Move hit target" : "Move missed target"); - Debug.WriteLine(" (diff: " + Math.Abs(tasklist.Current.BoundingRectangle.Y - targetPos) + ")"); - } + // Left bounds check + var leftBounds = SideBoundary(true, horizontal, tasklist); + if (targetPos <= leftBounds) + { + // Prevent X position ending up beyond the normal left aligned position + Debug.WriteLine("Target is more left than left/top aligned default, left/top aligning (" + targetPos + + " <= " + leftBounds + ")"); + Reset(trayWnd); + return true; + } - lasts[trayWnd] = horizontal ? last.Current.BoundingRectangle.Left : last.Current.BoundingRectangle.Top; + var tasklistPtr = (IntPtr) tasklist.Current.NativeWindowHandle; - return true; + if (horizontal) + { + SetWindowPos(tasklistPtr, IntPtr.Zero, RelativePos(targetPos, horizontal, tasklist), 0, 0, 0, + SWP_NOZORDER | SWP_NOSIZE | SWP_ASYNCWINDOWPOS); + Debug.Write("Final X Position: "); + Debug.WriteLine(tasklist.Current.BoundingRectangle.X); + Debug.Write( + tasklist.Current.BoundingRectangle.X == targetPos ? "Move hit target" : "Move missed target"); + Debug.WriteLine(" (diff: " + Math.Abs(tasklist.Current.BoundingRectangle.X - targetPos) + ")"); } + else + { + SetWindowPos(tasklistPtr, IntPtr.Zero, 0, RelativePos(targetPos, horizontal, tasklist), 0, 0, + SWP_NOZORDER | SWP_NOSIZE | SWP_ASYNCWINDOWPOS); + Debug.Write("Final Y Position: "); + Debug.WriteLine(tasklist.Current.BoundingRectangle.Y); + Debug.Write( + tasklist.Current.BoundingRectangle.Y == targetPos ? "Move hit target" : "Move missed target"); + Debug.WriteLine(" (diff: " + Math.Abs(tasklist.Current.BoundingRectangle.Y - targetPos) + ")"); + } + + _lasts[trayWnd] = horizontal ? last.Current.BoundingRectangle.Left : last.Current.BoundingRectangle.Top; + + return true; } private int RelativePos(double x, bool horizontal, AutomationElement element) { - int adjustment = SideBoundary(true, horizontal, element); + var adjustment = SideBoundary(true, horizontal, element); - double newPos = x - adjustment; + var newPos = x - adjustment; if (newPos < 0) { @@ -414,70 +423,68 @@ private int RelativePos(double x, bool horizontal, AutomationElement element) newPos = 0; } - return (int)newPos; + return (int) newPos; } private int SideBoundary(bool left, bool horizontal, AutomationElement element) { double adjustment = 0; - AutomationElement prevSibling = TreeWalker.ControlViewWalker.GetPreviousSibling(element); - AutomationElement nextSibling = TreeWalker.ControlViewWalker.GetNextSibling(element); - AutomationElement parent = TreeWalker.ControlViewWalker.GetParent(element); - if ((left && prevSibling != null)) + var prevSibling = TreeWalker.ControlViewWalker.GetPreviousSibling(element); + var nextSibling = TreeWalker.ControlViewWalker.GetNextSibling(element); + var parent = TreeWalker.ControlViewWalker.GetParent(element); + if (left && prevSibling != null) { - adjustment = horizontal ? prevSibling.Current.BoundingRectangle.Right : prevSibling.Current.BoundingRectangle.Bottom; - } else if (!left && nextSibling != null) + adjustment = horizontal + ? prevSibling.Current.BoundingRectangle.Right + : prevSibling.Current.BoundingRectangle.Bottom; + } + else if (!left && nextSibling != null) { - adjustment = horizontal ? nextSibling.Current.BoundingRectangle.Left : nextSibling.Current.BoundingRectangle.Top; + adjustment = horizontal + ? nextSibling.Current.BoundingRectangle.Left + : nextSibling.Current.BoundingRectangle.Top; } else if (parent != null) { if (horizontal) - { adjustment = left ? parent.Current.BoundingRectangle.Left : parent.Current.BoundingRectangle.Right; - } else - { + else adjustment = left ? parent.Current.BoundingRectangle.Top : parent.Current.BoundingRectangle.Bottom; - } - } if (horizontal) - { Debug.WriteLine((left ? "Left" : "Right") + " side boundary calulcated at " + adjustment); - } else - { + else Debug.WriteLine((left ? "Top" : "Bottom") + " side boundary calulcated at " + adjustment); - } - - return (int)adjustment; + + return (int) adjustment; } // Protected implementation of Dispose pattern. protected override void Dispose(bool disposing) { - if (disposed) + if (_disposed) return; if (disposing) { // Stop listening for new events - if (UIAeventHandler != null) + if (_uiaEventHandler != null) { //Automation.RemoveAutomationPropertyChangedEventHandler(tasklist, propChangeHandler); //TODO: Remove these from each taskbar - Automation.RemoveAutomationEventHandler(WindowPattern.WindowOpenedEvent, desktop, UIAeventHandler); - Automation.RemoveAutomationEventHandler(WindowPattern.WindowClosedEvent, desktop, UIAeventHandler); + Automation.RemoveAutomationEventHandler(WindowPattern.WindowOpenedEvent, Desktop, _uiaEventHandler); + Automation.RemoveAutomationEventHandler(WindowPattern.WindowClosedEvent, Desktop, _uiaEventHandler); } // Put icons back ResetAll(); // Hide tray icon, otherwise it will remain shown until user mouses over it - trayIcon.Visible = false; - trayIcon.Dispose(); + _trayIcon.Visible = false; + _trayIcon.Dispose(); } - disposed = true; + _disposed = true; } } -} +} \ No newline at end of file From 906ec2b22211df7e1fc1a9e6c6ffa6af3f9639c6 Mon Sep 17 00:00:00 2001 From: Adam Kauffman Date: Mon, 11 May 2020 02:42:40 -0700 Subject: [PATCH 2/4] Avoid abort thread Implements loop canceling with timeout abort fallback Remove all EventHandlers! Set StartupObject Fix bug in OnUIAutomationEvent by casting to list --- CenterTaskbar/CenterTaskbar.csproj | 3 + CenterTaskbar/Program.cs | 124 +++++++++++++++-------------- 2 files changed, 69 insertions(+), 58 deletions(-) diff --git a/CenterTaskbar/CenterTaskbar.csproj b/CenterTaskbar/CenterTaskbar.csproj index cf0d4b5..01dd477 100644 --- a/CenterTaskbar/CenterTaskbar.csproj +++ b/CenterTaskbar/CenterTaskbar.csproj @@ -72,6 +72,9 @@ false + + CenterTaskbar.Program + diff --git a/CenterTaskbar/Program.cs b/CenterTaskbar/Program.cs index d2378eb..ad50b77 100644 --- a/CenterTaskbar/Program.cs +++ b/CenterTaskbar/Program.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Threading; @@ -42,21 +43,20 @@ public class TrayApplication : ApplicationContext { private const string AppName = "CenterTaskbar"; private const string RunRegkey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"; + private const int OneSecond = 1000; private const int SWP_NOSIZE = 0x0001; - private const int SWP_NOZORDER = 0x0004; - //private const int SWP_SHOWWINDOW = 0x0040; private const int SWP_ASYNCWINDOWPOS = 0x4000; - private const string MSTaskListWClass = "MSTaskListWClass"; - //private const String ReBarWindow32 = "ReBarWindow32"; private const string ShellTrayWnd = "Shell_TrayWnd"; private const string ShellSecondaryTrayWnd = "Shell_SecondaryTrayWnd"; - private static readonly string ExecutablePath = "\"" + Application.ExecutablePath + "\""; + private static readonly string ExecutablePath = "\"" + Application.ExecutablePath + "\""; private static bool _disposed; + volatile bool _loopCancelled; + private static readonly AutomationElement Desktop = AutomationElement.RootElement; private static AutomationEventHandler _uiaEventHandler; private static AutomationPropertyChangedEventHandler _propChangeHandler; @@ -75,9 +75,9 @@ public class TrayApplication : ApplicationContext private readonly Dictionary _positionThreads = new Dictionary(); - public TrayApplication(string[] args) + public TrayApplication(IReadOnlyList args) { - if (args.Length > 0) + if (args.Count > 0) try { _activeFramerate = int.Parse(args[0]); @@ -164,7 +164,18 @@ private static void Exit(object sender, EventArgs e) private void CancelPositionThread() { - foreach (var thread in _positionThreads.Values) thread.Abort(); + _loopCancelled = true; + foreach (var thread in _positionThreads.Values) + { + // Give the thread time to exit gracefully. + if (!thread.Join(OneSecond * 3)) + { + // Only abort if we reach timeout waiting for the thread to end. + thread.Abort(); + } + } + + _loopCancelled = false; } private void Restart(object sender, EventArgs e) @@ -183,24 +194,24 @@ private static void Reset(AutomationElement trayWnd) { Debug.WriteLine("Begin Reset Calculation"); - var tasklist = trayWnd.FindFirst(TreeScope.Descendants, + var taskList = trayWnd.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ClassNameProperty, MSTaskListWClass)); - if (tasklist == null) + if (taskList == null) { Debug.WriteLine("Null values found, aborting reset"); return; } - var tasklistcontainer = TreeWalker.ControlViewWalker.GetParent(tasklist); - if (tasklistcontainer == null) + var taskListContainer = TreeWalker.ControlViewWalker.GetParent(taskList); + if (taskListContainer == null) { Debug.WriteLine("Null values found, aborting reset"); return; } - var tasklistPtr = (IntPtr) tasklist.Current.NativeWindowHandle; + var taskListPtr = (IntPtr) taskList.Current.NativeWindowHandle; - SetWindowPos(tasklistPtr, IntPtr.Zero, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_ASYNCWINDOWPOS); + SetWindowPos(taskListPtr, IntPtr.Zero, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_ASYNCWINDOWPOS); } private void Start() @@ -228,36 +239,32 @@ private void Start() _lasts.Clear(); foreach (AutomationElement trayWnd in lists) { - var tasklist = trayWnd.FindFirst(TreeScope.Descendants, - new PropertyCondition(AutomationElement.ClassNameProperty, MSTaskListWClass)); - if (tasklist == null) + var taskList = trayWnd.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ClassNameProperty, MSTaskListWClass)); + if (taskList == null) { Debug.WriteLine("Null values found, aborting"); continue; } _propChangeHandler = OnUIAutomationEvent; - Automation.AddAutomationPropertyChangedEventHandler(tasklist, TreeScope.Element, _propChangeHandler, - AutomationElement.BoundingRectangleProperty); + Automation.AddAutomationPropertyChangedEventHandler(taskList, TreeScope.Element, _propChangeHandler, AutomationElement.BoundingRectangleProperty); _bars.Add(trayWnd); - _children.Add(trayWnd, tasklist); + _children.Add(trayWnd, taskList); _positionThreads[trayWnd] = new Thread(LoopForPosition); _positionThreads[trayWnd].Start(trayWnd); } } _uiaEventHandler = OnUIAutomationEvent; - Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent, Desktop, TreeScope.Subtree, - _uiaEventHandler); - Automation.AddAutomationEventHandler(WindowPattern.WindowClosedEvent, Desktop, TreeScope.Subtree, - _uiaEventHandler); + Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent, Desktop, TreeScope.Subtree, _uiaEventHandler); + Automation.AddAutomationEventHandler(WindowPattern.WindowClosedEvent, Desktop, TreeScope.Subtree, _uiaEventHandler); } private void OnUIAutomationEvent(object src, AutomationEventArgs e) { Debug.Print("Event occured: {0}", e.EventId.ProgrammaticName); - foreach (var trayWnd in _bars) + foreach (var trayWnd in _bars.ToList()) if (!_positionThreads[trayWnd].IsAlive) { Debug.WriteLine("Starting new thead"); @@ -278,7 +285,8 @@ private void LoopForPosition(object trayWndObj) while (keepGoing < numberOfLoops) { if (!PositionLoop(trayWnd)) keepGoing += 1; - Task.Delay(1000 / _activeFramerate).Wait(); + if (_loopCancelled) break; + Task.Delay(OneSecond / _activeFramerate).Wait(); } Debug.WriteLine("LoopForPosition Thread ended."); @@ -288,8 +296,8 @@ private bool PositionLoop(AutomationElement trayWnd) { Debug.WriteLine("Begin Reposition Calculation"); - var tasklist = _children[trayWnd]; - var last = TreeWalker.ControlViewWalker.GetLastChild(tasklist); + var taskList = _children[trayWnd]; + var last = TreeWalker.ControlViewWalker.GetLastChild(taskList); if (last == null) { Debug.WriteLine("Null values found for items, aborting"); @@ -312,7 +320,7 @@ private bool PositionLoop(AutomationElement trayWnd) Debug.WriteLine("Size/location changed, recalculating center"); _lasts[trayWnd] = lastChildPos; - var first = TreeWalker.ControlViewWalker.GetFirstChild(tasklist); + var first = TreeWalker.ControlViewWalker.GetFirstChild(taskList); if (first == null) { Debug.WriteLine("Null values found for first child item, aborting"); @@ -323,23 +331,24 @@ private bool PositionLoop(AutomationElement trayWnd) ? last.Current.BoundingRectangle.Height / trayBounds.Height : last.Current.BoundingRectangle.Width / trayBounds.Width; Debug.WriteLine("UI Scale: " + scale); - var size = (lastChildPos - - (horizontal ? first.Current.BoundingRectangle.Left : first.Current.BoundingRectangle.Top)) / - scale; + var size = (lastChildPos - (horizontal + ? first.Current.BoundingRectangle.Left + : first.Current.BoundingRectangle.Top) + ) / scale; if (size < 0) { Debug.WriteLine("Size calculation failed"); return true; } - var tasklistcontainer = TreeWalker.ControlViewWalker.GetParent(tasklist); - if (tasklistcontainer == null) + var taskListContainer = TreeWalker.ControlViewWalker.GetParent(taskList); + if (taskListContainer == null) { Debug.WriteLine("Null values found for parent, aborting"); return true; } - var tasklistBounds = tasklist.Current.BoundingRectangle; + var taskListBounds = taskList.Current.BoundingRectangle; var barSize = horizontal ? trayWnd.Cached.BoundingRectangle.Width : trayWnd.Cached.BoundingRectangle.Height; var targetPos = Math.Round((barSize - size) / 2) + (horizontal ? trayBounds.X : trayBounds.Y); @@ -351,59 +360,54 @@ private bool PositionLoop(AutomationElement trayWnd) Debug.Write("Target abs " + (horizontal ? "X" : "Y") + " position: "); Debug.WriteLine(targetPos); - var delta = Math.Abs(targetPos - (horizontal ? tasklistBounds.X : tasklistBounds.Y)); + var delta = Math.Abs(targetPos - (horizontal ? taskListBounds.X : taskListBounds.Y)); // Previous bounds check if (delta <= 1) { // Already positioned within margin of error, avoid the unneeded MoveWindow call - Debug.WriteLine("Already positioned, ending to avoid the unneeded MoveWindow call (Delta: " + delta + - ")"); + Debug.WriteLine("Already positioned, ending to avoid the unneeded MoveWindow call (Delta: " + delta + ")"); return false; } // Right bounds check - var rightBounds = SideBoundary(false, horizontal, tasklist); + var rightBounds = SideBoundary(false, horizontal, taskList); if (targetPos + size > rightBounds) { // Shift off center when the bar is too big var extra = targetPos + size - rightBounds; - Debug.WriteLine("Shifting off center, too big and hitting right/bottom boundary (" + - (targetPos + size) + " > " + rightBounds + ") // " + extra); + Debug.WriteLine("Shifting off center, too big and hitting right/bottom boundary (" + (targetPos + size) + " > " + rightBounds + ") // " + extra); targetPos -= extra; } // Left bounds check - var leftBounds = SideBoundary(true, horizontal, tasklist); + var leftBounds = SideBoundary(true, horizontal, taskList); if (targetPos <= leftBounds) { // Prevent X position ending up beyond the normal left aligned position - Debug.WriteLine("Target is more left than left/top aligned default, left/top aligning (" + targetPos + - " <= " + leftBounds + ")"); + Debug.WriteLine("Target is more left than left/top aligned default, left/top aligning (" + targetPos + " <= " + leftBounds + ")"); Reset(trayWnd); return true; } - var tasklistPtr = (IntPtr) tasklist.Current.NativeWindowHandle; + var taskListPtr = (IntPtr) taskList.Current.NativeWindowHandle; if (horizontal) { - SetWindowPos(tasklistPtr, IntPtr.Zero, RelativePos(targetPos, horizontal, tasklist), 0, 0, 0, + SetWindowPos(taskListPtr, IntPtr.Zero, RelativePos(targetPos, horizontal, taskList), 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_ASYNCWINDOWPOS); Debug.Write("Final X Position: "); - Debug.WriteLine(tasklist.Current.BoundingRectangle.X); - Debug.Write( - tasklist.Current.BoundingRectangle.X == targetPos ? "Move hit target" : "Move missed target"); - Debug.WriteLine(" (diff: " + Math.Abs(tasklist.Current.BoundingRectangle.X - targetPos) + ")"); + Debug.WriteLine(taskList.Current.BoundingRectangle.X); + Debug.Write(taskList.Current.BoundingRectangle.X == targetPos ? "Move hit target" : "Move missed target"); + Debug.WriteLine(" (diff: " + Math.Abs(taskList.Current.BoundingRectangle.X - targetPos) + ")"); } else { - SetWindowPos(tasklistPtr, IntPtr.Zero, 0, RelativePos(targetPos, horizontal, tasklist), 0, 0, + SetWindowPos(taskListPtr, IntPtr.Zero, 0, RelativePos(targetPos, horizontal, taskList), 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_ASYNCWINDOWPOS); Debug.Write("Final Y Position: "); - Debug.WriteLine(tasklist.Current.BoundingRectangle.Y); - Debug.Write( - tasklist.Current.BoundingRectangle.Y == targetPos ? "Move hit target" : "Move missed target"); - Debug.WriteLine(" (diff: " + Math.Abs(tasklist.Current.BoundingRectangle.Y - targetPos) + ")"); + Debug.WriteLine(taskList.Current.BoundingRectangle.Y); + Debug.Write(taskList.Current.BoundingRectangle.Y == targetPos ? "Move hit target" : "Move missed target"); + Debug.WriteLine(" (diff: " + Math.Abs(taskList.Current.BoundingRectangle.Y - targetPos) + ")"); } _lasts[trayWnd] = horizontal ? last.Current.BoundingRectangle.Left : last.Current.BoundingRectangle.Top; @@ -411,7 +415,7 @@ private bool PositionLoop(AutomationElement trayWnd) return true; } - private int RelativePos(double x, bool horizontal, AutomationElement element) + private static int RelativePos(double x, bool horizontal, AutomationElement element) { var adjustment = SideBoundary(true, horizontal, element); @@ -426,7 +430,7 @@ private int RelativePos(double x, bool horizontal, AutomationElement element) return (int) newPos; } - private int SideBoundary(bool left, bool horizontal, AutomationElement element) + private static int SideBoundary(bool left, bool horizontal, AutomationElement element) { double adjustment = 0; var prevSibling = TreeWalker.ControlViewWalker.GetPreviousSibling(element); @@ -471,7 +475,11 @@ protected override void Dispose(bool disposing) // Stop listening for new events if (_uiaEventHandler != null) { - //Automation.RemoveAutomationPropertyChangedEventHandler(tasklist, propChangeHandler); //TODO: Remove these from each taskbar + foreach (var taskBar in _children) + { + Automation.RemoveAutomationPropertyChangedEventHandler(taskBar.Value, _propChangeHandler); + } + Automation.RemoveAutomationEventHandler(WindowPattern.WindowOpenedEvent, Desktop, _uiaEventHandler); Automation.RemoveAutomationEventHandler(WindowPattern.WindowClosedEvent, Desktop, _uiaEventHandler); } From 65a539b2395c96367102a715fd92212c401e2f2e Mon Sep 17 00:00:00 2001 From: Adam Kauffman Date: Mon, 11 May 2020 16:19:27 -0700 Subject: [PATCH 3/4] Implement Task pattern Make all threads in to tasks Implement Cancelation Token Convert foreach to Parallel.ForEach --- CenterTaskbar/CenterTaskbar.csproj | 2 +- CenterTaskbar/Program.cs | 63 ++++++++++++++++-------------- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/CenterTaskbar/CenterTaskbar.csproj b/CenterTaskbar/CenterTaskbar.csproj index 01dd477..614b73e 100644 --- a/CenterTaskbar/CenterTaskbar.csproj +++ b/CenterTaskbar/CenterTaskbar.csproj @@ -31,7 +31,7 @@ Michael Higgins Center Taskbar false - 5 + 9 1.1.0.%2a false true diff --git a/CenterTaskbar/Program.cs b/CenterTaskbar/Program.cs index ad50b77..817f08e 100644 --- a/CenterTaskbar/Program.cs +++ b/CenterTaskbar/Program.cs @@ -55,7 +55,7 @@ public class TrayApplication : ApplicationContext private static readonly string ExecutablePath = "\"" + Application.ExecutablePath + "\""; private static bool _disposed; - volatile bool _loopCancelled; + private CancellationTokenSource _loopCancellationTokenSource = new CancellationTokenSource(); private static readonly AutomationElement Desktop = AutomationElement.RootElement; private static AutomationEventHandler _uiaEventHandler; @@ -72,8 +72,8 @@ public class TrayApplication : ApplicationContext private readonly NotifyIcon _trayIcon; // private Thread positionThread; - private readonly Dictionary _positionThreads = - new Dictionary(); + private readonly Dictionary _positionThreads = + new Dictionary(); public TrayApplication(IReadOnlyList args) { @@ -164,18 +164,17 @@ private static void Exit(object sender, EventArgs e) private void CancelPositionThread() { - _loopCancelled = true; - foreach (var thread in _positionThreads.Values) + _loopCancellationTokenSource.Cancel(); + Parallel.ForEach(_positionThreads.Values.ToList(), theTask => { // Give the thread time to exit gracefully. - if (!thread.Join(OneSecond * 3)) - { - // Only abort if we reach timeout waiting for the thread to end. - thread.Abort(); - } - } + if (theTask.Wait(OneSecond * 3)) return; + + Debug.WriteLine("Timeout waiting for task to cancel!"); + theTask.Dispose(); + }); - _loopCancelled = false; + _loopCancellationTokenSource = new CancellationTokenSource(); } private void Restart(object sender, EventArgs e) @@ -187,7 +186,7 @@ private void Restart(object sender, EventArgs e) private void ResetAll() { CancelPositionThread(); - foreach (var trayWnd in _bars) Reset(trayWnd); + Parallel.ForEach(_bars.ToList(), Reset); } private static void Reset(AutomationElement trayWnd) @@ -237,23 +236,26 @@ private void Start() Debug.WriteLine(lists.Count + " bar(s) detected"); _lasts.Clear(); - foreach (AutomationElement trayWnd in lists) + Parallel.ForEach(lists.OfType(), trayWnd => { - var taskList = trayWnd.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ClassNameProperty, MSTaskListWClass)); + var taskList = trayWnd.FindFirst(TreeScope.Descendants, + new PropertyCondition(AutomationElement.ClassNameProperty, MSTaskListWClass)); if (taskList == null) { Debug.WriteLine("Null values found, aborting"); - continue; } + else + { + _propChangeHandler = OnUIAutomationEvent; + Automation.AddAutomationPropertyChangedEventHandler(taskList, TreeScope.Element, _propChangeHandler, + AutomationElement.BoundingRectangleProperty); - _propChangeHandler = OnUIAutomationEvent; - Automation.AddAutomationPropertyChangedEventHandler(taskList, TreeScope.Element, _propChangeHandler, AutomationElement.BoundingRectangleProperty); + _bars.Add(trayWnd); + _children.Add(trayWnd, taskList); - _bars.Add(trayWnd); - _children.Add(trayWnd, taskList); - _positionThreads[trayWnd] = new Thread(LoopForPosition); - _positionThreads[trayWnd].Start(trayWnd); - } + _positionThreads[trayWnd] = Task.Run(() => LoopForPosition(trayWnd), _loopCancellationTokenSource.Token); + } + }); } _uiaEventHandler = OnUIAutomationEvent; @@ -264,17 +266,18 @@ private void Start() private void OnUIAutomationEvent(object src, AutomationEventArgs e) { Debug.Print("Event occured: {0}", e.EventId.ProgrammaticName); - foreach (var trayWnd in _bars.ToList()) - if (!_positionThreads[trayWnd].IsAlive) + Parallel.ForEach(_bars.ToList(), trayWnd => + { + if (_positionThreads[trayWnd].IsCompleted) { Debug.WriteLine("Starting new thead"); - _positionThreads[trayWnd] = new Thread(LoopForPosition); - _positionThreads[trayWnd].Start(trayWnd); + _positionThreads[trayWnd] = Task.Run(() => LoopForPosition(trayWnd), _loopCancellationTokenSource.Token); } else { Debug.WriteLine("Thread already exists"); } + }); } private void LoopForPosition(object trayWndObj) @@ -285,7 +288,7 @@ private void LoopForPosition(object trayWndObj) while (keepGoing < numberOfLoops) { if (!PositionLoop(trayWnd)) keepGoing += 1; - if (_loopCancelled) break; + if (_loopCancellationTokenSource.IsCancellationRequested) break; Task.Delay(OneSecond / _activeFramerate).Wait(); } @@ -457,9 +460,9 @@ private static int SideBoundary(bool left, bool horizontal, AutomationElement el } if (horizontal) - Debug.WriteLine((left ? "Left" : "Right") + " side boundary calulcated at " + adjustment); + Debug.WriteLine((left ? "Left" : "Right") + " side boundary calculated at " + adjustment); else - Debug.WriteLine((left ? "Top" : "Bottom") + " side boundary calulcated at " + adjustment); + Debug.WriteLine((left ? "Top" : "Bottom") + " side boundary calculated at " + adjustment); return (int) adjustment; } From a4e77f86171a27496e3f40bcbb3a6b4c81b78f4d Mon Sep 17 00:00:00 2001 From: Adam Kauffman Date: Mon, 11 May 2020 20:16:17 -0700 Subject: [PATCH 4/4] minor correction for clarity --- CenterTaskbar/DisplaySettings.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/CenterTaskbar/DisplaySettings.cs b/CenterTaskbar/DisplaySettings.cs index dc9c936..3196aa5 100644 --- a/CenterTaskbar/DisplaySettings.cs +++ b/CenterTaskbar/DisplaySettings.cs @@ -11,13 +11,12 @@ internal static class DisplaySettings const int ENUM_CURRENT_SETTINGS = -1; const int ENUM_REGISTRY_SETTINGS = -2; - [StructLayout(LayoutKind.Sequential)] + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] private struct DEVMODE { - - private const int CCHDEVICENAME = 0x20; - private const int CCHFORMNAME = 0x20; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)] + private const int CCHDEVICENAME = 32; + private const int CCHFORMNAME = 32; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)] public string dmDeviceName; public short dmSpecVersion; public short dmDriverVersion; @@ -33,7 +32,7 @@ private struct DEVMODE public short dmYResolution; public short dmTTOption; public short dmCollate; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)] public string dmFormName; public short dmLogPixels; public int dmBitsPerPel; @@ -49,7 +48,6 @@ private struct DEVMODE public int dmReserved2; public int dmPanningWidth; public int dmPanningHeight; - } //public static void ListAllDisplayModes()