diff --git a/src/modules/imageresizer/ui/App.xaml b/src/modules/imageresizer/ui/App.xaml index 8b64a919da..1eb9d326b6 100644 --- a/src/modules/imageresizer/ui/App.xaml +++ b/src/modules/imageresizer/ui/App.xaml @@ -3,74 +3,83 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:m="clr-namespace:ImageResizer.Models" xmlns:sys="clr-namespace:System;assembly=System.Runtime" - xmlns:v="clr-namespace:ImageResizer.Views"> + xmlns:v="clr-namespace:ImageResizer.Views" + xmlns:ui="http://schemas.modernwpf.com/2019"> - + + + + + + + - - - - - + + + + - - - - - - - - - - - + + - + + + + + + + + diff --git a/src/modules/imageresizer/ui/App.xaml.cs b/src/modules/imageresizer/ui/App.xaml.cs index 1d6fba2cd5..c95cffe381 100644 --- a/src/modules/imageresizer/ui/App.xaml.cs +++ b/src/modules/imageresizer/ui/App.xaml.cs @@ -13,8 +13,12 @@ using ImageResizer.Views; namespace ImageResizer { +#pragma warning disable CA1001 // Types that own disposable fields should be disposable public partial class App : Application +#pragma warning restore CA1001 // Types that own disposable fields should be disposable { + private ThemeManager _themeManager; + static App() { Console.InputEncoding = Encoding.Unicode; @@ -28,6 +32,8 @@ namespace ImageResizer var mainWindow = new MainWindow(new MainViewModel(batch, Settings.Default)); mainWindow.Show(); + _themeManager = new ThemeManager(this); + // Temporary workaround for issue #1273 BecomeForegroundWindow(new System.Windows.Interop.WindowInteropHelper(mainWindow).Handle); } diff --git a/src/modules/imageresizer/ui/ImageResizerUI.csproj b/src/modules/imageresizer/ui/ImageResizerUI.csproj index e7a580b509..54fb3f17be 100644 --- a/src/modules/imageresizer/ui/ImageResizerUI.csproj +++ b/src/modules/imageresizer/ui/ImageResizerUI.csproj @@ -61,10 +61,12 @@ + all + all diff --git a/src/modules/imageresizer/ui/Themes/Dark.xaml b/src/modules/imageresizer/ui/Themes/Dark.xaml new file mode 100644 index 0000000000..ad481d6c66 --- /dev/null +++ b/src/modules/imageresizer/ui/Themes/Dark.xaml @@ -0,0 +1,29 @@ + + + + Dark.Accent1 + PowerToysImageResizer + Accent1 (Dark) + Dark + Accent1 + Black + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/modules/imageresizer/ui/Themes/HighContrast1.xaml b/src/modules/imageresizer/ui/Themes/HighContrast1.xaml new file mode 100644 index 0000000000..d19932cf9d --- /dev/null +++ b/src/modules/imageresizer/ui/Themes/HighContrast1.xaml @@ -0,0 +1,29 @@ + + + + HighContrast.Accent2 + PowerToysImageResizer + Accent2 (HighContrast) + HighContrast + Accent2 + White + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/modules/imageresizer/ui/Themes/HighContrast2.xaml b/src/modules/imageresizer/ui/Themes/HighContrast2.xaml new file mode 100644 index 0000000000..8d21136102 --- /dev/null +++ b/src/modules/imageresizer/ui/Themes/HighContrast2.xaml @@ -0,0 +1,30 @@ + + + + HighContrast.Accent3 + PowerToysImageResizer + Accent3 (HighContrast) + HighContrast + Accent3 + White + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/modules/imageresizer/ui/Themes/HighContrastBlack.xaml b/src/modules/imageresizer/ui/Themes/HighContrastBlack.xaml new file mode 100644 index 0000000000..4ee3b468da --- /dev/null +++ b/src/modules/imageresizer/ui/Themes/HighContrastBlack.xaml @@ -0,0 +1,30 @@ + + + + HighContrast.Accent4 + PowerToysImageResizer + Accent4 (HighContrast) + HighContrast + Accent4 + White + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/modules/imageresizer/ui/Themes/HighContrastWhite.xaml b/src/modules/imageresizer/ui/Themes/HighContrastWhite.xaml new file mode 100644 index 0000000000..6225708456 --- /dev/null +++ b/src/modules/imageresizer/ui/Themes/HighContrastWhite.xaml @@ -0,0 +1,30 @@ + + + + HighContrast.Accent5 + PowerToysImageResizer + Accent5 (HighContrast) + HighContrast + Accent5 + White + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/modules/imageresizer/ui/Themes/Light.xaml b/src/modules/imageresizer/ui/Themes/Light.xaml new file mode 100644 index 0000000000..c55f932373 --- /dev/null +++ b/src/modules/imageresizer/ui/Themes/Light.xaml @@ -0,0 +1,30 @@ + + + + Light.Accent1 + PowerToysImageResizer + Accent1 (Light) + Light + Accent1 + White + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/modules/imageresizer/ui/Utilities/ThemeManager.cs b/src/modules/imageresizer/ui/Utilities/ThemeManager.cs new file mode 100644 index 0000000000..15c47c936f --- /dev/null +++ b/src/modules/imageresizer/ui/Utilities/ThemeManager.cs @@ -0,0 +1,201 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Linq; +using System.Windows; +using ControlzEx.Theming; +using MahApps.Metro.Theming; +using Microsoft.Win32; + +namespace ImageResizer.Utilities +{ + public class ThemeManager : IDisposable + { + private readonly Application _app; + private const string LightTheme = "Light.Accent1"; + private const string DarkTheme = "Dark.Accent1"; + private const string HighContrastOneTheme = "HighContrast.Accent2"; + private const string HighContrastTwoTheme = "HighContrast.Accent3"; + private const string HighContrastBlackTheme = "HighContrast.Accent4"; + private const string HighContrastWhiteTheme = "HighContrast.Accent5"; + + private Theme currentTheme; + private bool _disposed; + + public event ThemeChangedHandler ThemeChanged; + + public ThemeManager(Application app) + { + _app = app; + + Uri highContrastOneThemeUri = new Uri("pack://application:,,,/Themes/HighContrast1.xaml"); + Uri highContrastTwoThemeUri = new Uri("pack://application:,,,/Themes/HighContrast2.xaml"); + Uri highContrastBlackThemeUri = new Uri("pack://application:,,,/Themes/HighContrastWhite.xaml"); + Uri highContrastWhiteThemeUri = new Uri("pack://application:,,,/Themes/HighContrastBlack.xaml"); + Uri lightThemeUri = new Uri("pack://application:,,,/Themes/Light.xaml"); + Uri darkThemeUri = new Uri("pack://application:,,,/Themes/Dark.xaml"); + + ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme( + new LibraryTheme( + highContrastOneThemeUri, + MahAppsLibraryThemeProvider.DefaultInstance)); + ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme( + new LibraryTheme( + highContrastTwoThemeUri, + MahAppsLibraryThemeProvider.DefaultInstance)); + ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme( + new LibraryTheme( + highContrastBlackThemeUri, + MahAppsLibraryThemeProvider.DefaultInstance)); + ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme( + new LibraryTheme( + highContrastWhiteThemeUri, + MahAppsLibraryThemeProvider.DefaultInstance)); + ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme( + new LibraryTheme( + lightThemeUri, + MahAppsLibraryThemeProvider.DefaultInstance)); + ControlzEx.Theming.ThemeManager.Current.AddLibraryTheme( + new LibraryTheme( + darkThemeUri, + MahAppsLibraryThemeProvider.DefaultInstance)); + + ResetTheme(); + ControlzEx.Theming.ThemeManager.Current.ThemeSyncMode = ThemeSyncMode.SyncWithAppMode; + ControlzEx.Theming.ThemeManager.Current.ThemeChanged += Current_ThemeChanged; + SystemParameters.StaticPropertyChanged += SystemParameters_StaticPropertyChanged; + } + + private void SystemParameters_StaticPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(SystemParameters.HighContrast)) + { + ResetTheme(); + } + } + + public Theme GetCurrentTheme() + { + return currentTheme; + } + + private static Theme GetHighContrastBaseType() + { + string registryKey = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes"; + string theme = (string)Registry.GetValue(registryKey, "CurrentTheme", string.Empty); + theme = theme.Split('\\').Last().Split('.').First().ToString(); + + switch (theme) + { + case "hc1": + return Theme.HighContrastOne; + case "hc2": + return Theme.HighContrastTwo; + case "hcwhite": + return Theme.HighContrastWhite; + case "hcblack": + return Theme.HighContrastBlack; + default: + return Theme.None; + } + } + + private void ResetTheme() + { + if (SystemParameters.HighContrast) + { + Theme highContrastBaseType = GetHighContrastBaseType(); + ChangeTheme(highContrastBaseType); + } + else + { + string baseColor = WindowsThemeHelper.GetWindowsBaseColor(); + ChangeTheme((Theme)Enum.Parse(typeof(Theme), baseColor)); + } + } + + private void ChangeTheme(Theme theme) + { + Theme oldTheme = currentTheme; + if (theme == currentTheme) + { + return; + } + + if (theme == Theme.HighContrastOne) + { + ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastOneTheme); + currentTheme = Theme.HighContrastOne; + } + else if (theme == Theme.HighContrastTwo) + { + ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastTwoTheme); + currentTheme = Theme.HighContrastTwo; + } + else if (theme == Theme.HighContrastWhite) + { + ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastWhiteTheme); + currentTheme = Theme.HighContrastWhite; + } + else if (theme == Theme.HighContrastBlack) + { + ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, HighContrastBlackTheme); + currentTheme = Theme.HighContrastBlack; + } + else if (theme == Theme.Light) + { + ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, LightTheme); + currentTheme = Theme.Light; + } + else if (theme == Theme.Dark) + { + ControlzEx.Theming.ThemeManager.Current.ChangeTheme(_app, DarkTheme); + currentTheme = Theme.Dark; + } + else + { + currentTheme = Theme.None; + } + + ThemeChanged?.Invoke(oldTheme, currentTheme); + } + + private void Current_ThemeChanged(object sender, ThemeChangedEventArgs e) + { + ResetTheme(); + } + + protected virtual void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + ControlzEx.Theming.ThemeManager.Current.ThemeChanged -= Current_ThemeChanged; + SystemParameters.StaticPropertyChanged -= SystemParameters_StaticPropertyChanged; + _disposed = true; + } + } + } + + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } + + public delegate void ThemeChangedHandler(Theme oldTheme, Theme newTheme); + + public enum Theme + { + None, + Light, + Dark, + HighContrastOne, + HighContrastTwo, + HighContrastBlack, + HighContrastWhite, + } +} diff --git a/src/modules/imageresizer/ui/Views/InputPage.xaml b/src/modules/imageresizer/ui/Views/InputPage.xaml index ff9fa01895..5812779085 100644 --- a/src/modules/imageresizer/ui/Views/InputPage.xaml +++ b/src/modules/imageresizer/ui/Views/InputPage.xaml @@ -6,7 +6,7 @@ xmlns:p="clr-namespace:ImageResizer.Properties" MinWidth="350"> - +