From 6a4524b2e2b62779391febf997d92b726a599f9f Mon Sep 17 00:00:00 2001 From: Chris Kaczor Date: Tue, 6 May 2014 10:20:34 -0400 Subject: [PATCH] Support for locking/unlocking and closing other windows --- .../FloatingStatusWindow.cs | 42 ++++++++-- .../FloatingStatusWindowLibrary.csproj | 1 + .../MainWindow.xaml.cs | 60 ++++++++------- .../Properties/Resources.Designer.cs | 45 +++++++++++ .../Properties/Resources.resx | 15 ++++ FloatingStatusWindowLibrary/WindowManager.cs | 77 +++++++++++++++++++ FloatingStatusWindows.sln | 15 +++- StartAll.bat | 6 ++ 8 files changed, 226 insertions(+), 35 deletions(-) create mode 100644 FloatingStatusWindowLibrary/WindowManager.cs create mode 100644 StartAll.bat diff --git a/FloatingStatusWindowLibrary/FloatingStatusWindow.cs b/FloatingStatusWindowLibrary/FloatingStatusWindow.cs index 20d3398..c3431df 100644 --- a/FloatingStatusWindowLibrary/FloatingStatusWindow.cs +++ b/FloatingStatusWindowLibrary/FloatingStatusWindow.cs @@ -1,4 +1,6 @@ -using Hardcodet.Wpf.TaskbarNotification; +using Common.Native; +using FloatingStatusWindowLibrary.Properties; +using Hardcodet.Wpf.TaskbarNotification; using System; using System.Windows; using System.Windows.Controls; @@ -15,6 +17,9 @@ namespace FloatingStatusWindowLibrary private readonly MainWindow _mainWindow; private readonly TaskbarIcon _taskbarIcon; + private readonly MenuItem _allWindowsMenuItem; + private readonly Separator _allWindowsSeparator; + private readonly MenuItem _lockMenuItem; private readonly MenuItem _autoStartMenuItem; @@ -27,14 +32,34 @@ namespace FloatingStatusWindowLibrary var contextMenu = new ContextMenu(); contextMenu.Opened += HandleContextMenuOpened; - var optionsMenu = new MenuItem { Name = "contextMenuItemOptions", Header = "Window" }; + _allWindowsMenuItem = new MenuItem { Header = Resources.AllWindowsMenu }; + contextMenu.Items.Add(_allWindowsMenuItem); + + var menuItem = new MenuItem { Header = Resources.ContextMenuLock }; + menuItem.Click += (sender, args) => WindowManager.SetLockOnAll(true); + _allWindowsMenuItem.Items.Add(menuItem); + + menuItem = new MenuItem { Header = Resources.ContextMenuUnlock }; + menuItem.Click += (sender, args) => WindowManager.SetLockOnAll(false); + _allWindowsMenuItem.Items.Add(menuItem); + + _allWindowsMenuItem.Items.Add(new Separator()); + + menuItem = new MenuItem { Header = Resources.ContextMenuClose }; + menuItem.Click += (sender, args) => WindowManager.CloseAll(); + _allWindowsMenuItem.Items.Add(menuItem); + + _allWindowsSeparator = new Separator(); + contextMenu.Items.Add(_allWindowsSeparator); + + var optionsMenu = new MenuItem { Name = "contextMenuItemOptions", Header = Resources.WindowMenu }; contextMenu.Items.Add(optionsMenu); _lockMenuItem = new MenuItem { Name = "contextMenuItemLocked", IsChecked = false, - Header = Properties.Resources.ContextMenuLocked + Header = Resources.ContextMenuLocked }; _lockMenuItem.Click += HandleLockedMenuItemClicked; optionsMenu.Items.Add(_lockMenuItem); @@ -47,7 +72,7 @@ namespace FloatingStatusWindowLibrary { Name = "contextMenuItemAutoStart", IsChecked = StartManager.AutoStartEnabled, - Header = Properties.Resources.ContextMenuAutoStart + Header = Resources.ContextMenuAutoStart }; _autoStartMenuItem.Click += (sender, args) => StartManager.AutoStartEnabled = !StartManager.AutoStartEnabled; @@ -56,10 +81,10 @@ namespace FloatingStatusWindowLibrary optionsMenu.Items.Add(new Separator()); - var menuItem = new MenuItem + menuItem = new MenuItem { Name = "contextMenuChangeAppearance", - Header = Properties.Resources.ContextMenuChangeAppearance + Header = Resources.ContextMenuChangeAppearance }; menuItem.Click += HandleChangeAppearancemMenuItemClick; optionsMenu.Items.Add(menuItem); @@ -69,7 +94,7 @@ namespace FloatingStatusWindowLibrary menuItem = new MenuItem { Name = "contextMenuItemExit", - Header = Properties.Resources.ContextMenuExit + Header = Resources.ContextMenuExit }; menuItem.Click += HandleExitMenuItemClick; contextMenu.Items.Add(menuItem); @@ -117,6 +142,9 @@ namespace FloatingStatusWindowLibrary if (_autoStartMenuItem != null) _autoStartMenuItem.IsChecked = StartManager.AutoStartEnabled; + + _allWindowsMenuItem.Visibility = WindowManager.GetWindowList().Count == 0 ? Visibility.Collapsed : Visibility.Visible; + _allWindowsSeparator.Visibility = _allWindowsMenuItem.Visibility; } public void SetText(string text) diff --git a/FloatingStatusWindowLibrary/FloatingStatusWindowLibrary.csproj b/FloatingStatusWindowLibrary/FloatingStatusWindowLibrary.csproj index 41267fb..caea1a4 100644 --- a/FloatingStatusWindowLibrary/FloatingStatusWindowLibrary.csproj +++ b/FloatingStatusWindowLibrary/FloatingStatusWindowLibrary.csproj @@ -73,6 +73,7 @@ Resources.resx + PublicResXFileCodeGenerator diff --git a/FloatingStatusWindowLibrary/MainWindow.xaml.cs b/FloatingStatusWindowLibrary/MainWindow.xaml.cs index 68ce79b..53921ae 100644 --- a/FloatingStatusWindowLibrary/MainWindow.xaml.cs +++ b/FloatingStatusWindowLibrary/MainWindow.xaml.cs @@ -1,10 +1,11 @@ -using System; +using Common.Wpf.Windows; +using System; using System.Collections.Generic; using System.Windows; using System.Windows.Interop; using System.Windows.Media; using System.Windows.Shell; -using Common.Native; +using System.Windows.Threading; namespace FloatingStatusWindowLibrary { @@ -13,6 +14,7 @@ namespace FloatingStatusWindowLibrary private const int WindowCaptionHeight = 24; private readonly WindowChrome _windowChrome; + private readonly Dispatcher _dispatcher; private WindowSettings _windowSettings; public WindowSettings WindowSettings @@ -44,6 +46,8 @@ namespace FloatingStatusWindowLibrary { InitializeComponent(); + _dispatcher = Dispatcher.CurrentDispatcher; + // Create and set the window chrome _windowChrome = new WindowChrome { CaptionHeight = WindowCaptionHeight }; WindowChrome.SetWindowChrome(this, _windowChrome); @@ -71,6 +75,30 @@ namespace FloatingStatusWindowLibrary _windowSettings.Apply(); } + protected override IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) + { + if (msg == WindowManager.SetLockMessage) + { + var lockState = (wParam == (IntPtr) 1); + + _dispatcher.InvokeAsync(() => + { + WindowSettings.Locked = lockState; + Locked = lockState; + }); + + return IntPtr.Zero; + } + + if (msg == WindowManager.CloseMessage) + { + _dispatcher.InvokeAsync(Close); + return IntPtr.Zero; + } + + return base.WndProc(hwnd, msg, wParam, lParam, ref handled); + } + protected override void OnLocationChanged(EventArgs e) { base.OnLocationChanged(e); @@ -85,36 +113,14 @@ namespace FloatingStatusWindowLibrary _windowSettings.Size = new Size(Width, Height); } - private List _windowList; - private IntPtr _windowHandle; - protected override List OtherWindows + protected override List OtherWindows { get { - _windowList = new List(); - _windowHandle = new WindowInteropHelper(this).Handle; + var windowHandle = new WindowInteropHelper(this).Handle; - Functions.User32.EnumWindows(EnumWindowProc, IntPtr.Zero); - - return _windowList; + return WindowManager.GetWindowList(windowHandle); } } - - private bool EnumWindowProc(IntPtr hWnd, IntPtr lParam) - { - var windowText = Functions.Window.GetText(hWnd); - - if (windowText == "FloatingStatusWindow" && hWnd != _windowHandle) - { - var windowPlacement = new Structures.WindowPlacement(); - Functions.User32.GetWindowPlacement(hWnd, ref windowPlacement); - - var p = windowPlacement.NormalPosition; - - _windowList.Add(new Rect(p.X, p.Y, p.Width, p.Height)); - } - - return true; - } } } diff --git a/FloatingStatusWindowLibrary/Properties/Resources.Designer.cs b/FloatingStatusWindowLibrary/Properties/Resources.Designer.cs index 905e843..5760027 100644 --- a/FloatingStatusWindowLibrary/Properties/Resources.Designer.cs +++ b/FloatingStatusWindowLibrary/Properties/Resources.Designer.cs @@ -60,6 +60,15 @@ namespace FloatingStatusWindowLibrary.Properties { } } + /// + /// Looks up a localized string similar to All Windows. + /// + public static string AllWindowsMenu { + get { + return ResourceManager.GetString("AllWindowsMenu", resourceCulture); + } + } + /// /// Looks up a localized string similar to Bottom. /// @@ -114,6 +123,15 @@ namespace FloatingStatusWindowLibrary.Properties { } } + /// + /// Looks up a localized string similar to Close. + /// + public static string ContextMenuClose { + get { + return ResourceManager.GetString("ContextMenuClose", resourceCulture); + } + } + /// /// Looks up a localized string similar to Exit. /// @@ -123,6 +141,15 @@ namespace FloatingStatusWindowLibrary.Properties { } } + /// + /// Looks up a localized string similar to Lock. + /// + public static string ContextMenuLock { + get { + return ResourceManager.GetString("ContextMenuLock", resourceCulture); + } + } + /// /// Looks up a localized string similar to Locked. /// @@ -132,6 +159,15 @@ namespace FloatingStatusWindowLibrary.Properties { } } + /// + /// Looks up a localized string similar to Unlock. + /// + public static string ContextMenuUnlock { + get { + return ResourceManager.GetString("ContextMenuUnlock", resourceCulture); + } + } + /// /// Looks up a localized string similar to Font _name:. /// @@ -221,5 +257,14 @@ namespace FloatingStatusWindowLibrary.Properties { return ResourceManager.GetString("VerticalAlignment", resourceCulture); } } + + /// + /// Looks up a localized string similar to Window. + /// + public static string WindowMenu { + get { + return ResourceManager.GetString("WindowMenu", resourceCulture); + } + } } } diff --git a/FloatingStatusWindowLibrary/Properties/Resources.resx b/FloatingStatusWindowLibrary/Properties/Resources.resx index 0d2ddcc..e889322 100644 --- a/FloatingStatusWindowLibrary/Properties/Resources.resx +++ b/FloatingStatusWindowLibrary/Properties/Resources.resx @@ -117,6 +117,9 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + All Windows + Bottom @@ -135,12 +138,21 @@ Change Appearance... + + Close + Exit + + Lock + Locked + + Unlock + Font _name: @@ -171,4 +183,7 @@ _Vertical alignment: + + Window + \ No newline at end of file diff --git a/FloatingStatusWindowLibrary/WindowManager.cs b/FloatingStatusWindowLibrary/WindowManager.cs new file mode 100644 index 0000000..97a30a3 --- /dev/null +++ b/FloatingStatusWindowLibrary/WindowManager.cs @@ -0,0 +1,77 @@ +using Common.Native; +using Common.Wpf.Windows; +using System; +using System.Collections.Generic; + +namespace FloatingStatusWindowLibrary +{ + public static class WindowManager + { + private const string WindowMessageSetLock = "FloatingStatusWindowLibrary_SetLock"; + private const string WindowMessageClose = "FloatingStatusWindowLibrary_Close"; + + public static uint SetLockMessage { get; set; } + public static uint CloseMessage { get; set; } + + static WindowManager() + { + SetLockMessage = Functions.User32.RegisterWindowMessage(WindowMessageSetLock); + CloseMessage = Functions.User32.RegisterWindowMessage(WindowMessageClose); + } + + private static readonly object WindowLocker = new object(); + + private static List _windowList; + private static IntPtr _excludeHandle; + + public static List GetWindowList() + { + lock (WindowLocker) + { + _windowList = new List(); + _excludeHandle = IntPtr.Zero; + + Functions.User32.EnumWindows(EnumWindowProc, IntPtr.Zero); + + return _windowList; + } + } + + public static List GetWindowList(IntPtr excludeHandle) + { + lock (WindowLocker) + { + _windowList = new List(); + _excludeHandle = excludeHandle; + + Functions.User32.EnumWindows(EnumWindowProc, IntPtr.Zero); + + return _windowList; + } + } + + private static bool EnumWindowProc(IntPtr hWnd, IntPtr lParam) + { + var windowText = Functions.Window.GetText(hWnd); + + if (windowText == "FloatingStatusWindow" && hWnd != _excludeHandle) + _windowList.Add(new WindowInformation(hWnd)); + + return true; + } + + public static void SetLockOnAll(bool locked) + { + var lockState = locked ? (IntPtr) 1 : (IntPtr) 0; + + foreach (var w in GetWindowList()) + Functions.User32.SendMessage(w.Handle, SetLockMessage, lockState, IntPtr.Zero); + } + + public static void CloseAll() + { + foreach (var w in GetWindowList()) + Functions.User32.SendMessage(w.Handle, CloseMessage, IntPtr.Zero, IntPtr.Zero); + } + } +} diff --git a/FloatingStatusWindows.sln b/FloatingStatusWindows.sln index 7973cf8..2d37f68 100644 --- a/FloatingStatusWindows.sln +++ b/FloatingStatusWindows.sln @@ -33,7 +33,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WoWRealmStatusWindow", "..\ {F023A16C-2F13-4A87-A8B7-22C43C4A58A4} = {F023A16C-2F13-4A87-A8B7-22C43C4A58A4} EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FloatingStatusWindowLibrary", "..\FloatingStatusWindowLibrary\FloatingStatusWindowLibrary\FloatingStatusWindowLibrary.csproj", "{F023A16C-2F13-4A87-A8B7-22C43C4A58A4}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FloatingStatusWindowLibrary", "FloatingStatusWindowLibrary\FloatingStatusWindowLibrary.csproj", "{F023A16C-2F13-4A87-A8B7-22C43C4A58A4}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.Wpf", "..\Common.Wpf\Common.Wpf.csproj", "{0074C983-550E-4094-9E8C-F566FB669297}" EndProject @@ -41,6 +41,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.Native", "..\Common. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenHardwareMonitorLib", "..\..\Public\OpenHardwareMonitor\OpenHardwareMonitorLib.csproj", "{B0397530-545A-471D-BB74-027AE456DF1A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MinecraftStatusWindow", "..\MinecraftStatusWindow\MinecraftStatusWindow.csproj", "{D3ADE27E-4645-4C31-B4B2-8A64EF6984B0}" + ProjectSection(ProjectDependencies) = postProject + {F023A16C-2F13-4A87-A8B7-22C43C4A58A4} = {F023A16C-2F13-4A87-A8B7-22C43C4A58A4} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -139,6 +144,14 @@ Global {B0397530-545A-471D-BB74-027AE456DF1A}.Release|Any CPU.Build.0 = Release|Any CPU {B0397530-545A-471D-BB74-027AE456DF1A}.Release|x64.ActiveCfg = Release|Any CPU {B0397530-545A-471D-BB74-027AE456DF1A}.Release|x86.ActiveCfg = Release|Any CPU + {D3ADE27E-4645-4C31-B4B2-8A64EF6984B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D3ADE27E-4645-4C31-B4B2-8A64EF6984B0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D3ADE27E-4645-4C31-B4B2-8A64EF6984B0}.Debug|x64.ActiveCfg = Debug|Any CPU + {D3ADE27E-4645-4C31-B4B2-8A64EF6984B0}.Debug|x86.ActiveCfg = Debug|Any CPU + {D3ADE27E-4645-4C31-B4B2-8A64EF6984B0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D3ADE27E-4645-4C31-B4B2-8A64EF6984B0}.Release|Any CPU.Build.0 = Release|Any CPU + {D3ADE27E-4645-4C31-B4B2-8A64EF6984B0}.Release|x64.ActiveCfg = Release|Any CPU + {D3ADE27E-4645-4C31-B4B2-8A64EF6984B0}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/StartAll.bat b/StartAll.bat new file mode 100644 index 0000000..2bd259f --- /dev/null +++ b/StartAll.bat @@ -0,0 +1,6 @@ +start D:\Code\Personal\WeatherStatusWindow\bin\Debug\WeatherStatusWindow.exe +start D:\Code\Personal\WoWRealmStatusWindow\bin\Debug\WoWRealmStatusWindow.exe +start D:\Code\Personal\WaveUpgradeMonitorStatusWindow\bin\Debug\WaveUpgradeMonitorStatusWindow.exe +start D:\Code\Personal\SystemTemperatureStatusWindow\bin\Debug\SystemTemperatureStatusWindow.exe +start D:\Code\Personal\ProcessCpuUsageStatusWindow\bin\Debug\ProcessCpuUsageStatusWindow.exe +start D:\Code\Personal\MonitStatusWindow\bin\Debug\MonitStatusWindow.exe