Added theming support

This commit is contained in:
Niels Laute
2020-11-07 15:51:38 +01:00
parent 65ce8c760d
commit 36fd030075
11 changed files with 449 additions and 53 deletions

View File

@@ -3,9 +3,17 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:m="clr-namespace:ImageResizer.Models" xmlns:m="clr-namespace:ImageResizer.Models"
xmlns:sys="clr-namespace:System;assembly=System.Runtime" 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">
<Application.Resources> <Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ui:ThemeResources />
<ui:XamlControlsResources />
<!-- Other merged dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<ObjectDataProvider x:Key="ResizeFitValues" <ObjectDataProvider x:Key="ResizeFitValues"
MethodName="GetValues" MethodName="GetValues"
ObjectType="sys:Enum"> ObjectType="sys:Enum">
@@ -71,6 +79,7 @@
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Style> </Style>
</Application.Resources>
</ResourceDictionary>
</Application.Resources>
</Application> </Application>

View File

@@ -13,8 +13,12 @@ using ImageResizer.Views;
namespace ImageResizer namespace ImageResizer
{ {
#pragma warning disable CA1001 // Types that own disposable fields should be disposable
public partial class App : Application public partial class App : Application
#pragma warning restore CA1001 // Types that own disposable fields should be disposable
{ {
private ThemeManager _themeManager;
static App() static App()
{ {
Console.InputEncoding = Encoding.Unicode; Console.InputEncoding = Encoding.Unicode;
@@ -28,6 +32,8 @@ namespace ImageResizer
var mainWindow = new MainWindow(new MainViewModel(batch, Settings.Default)); var mainWindow = new MainWindow(new MainViewModel(batch, Settings.Default));
mainWindow.Show(); mainWindow.Show();
_themeManager = new ThemeManager(this);
// Temporary workaround for issue #1273 // Temporary workaround for issue #1273
BecomeForegroundWindow(new System.Windows.Interop.WindowInteropHelper(mainWindow).Handle); BecomeForegroundWindow(new System.Windows.Interop.WindowInteropHelper(mainWindow).Handle);
} }

View File

@@ -61,10 +61,12 @@
<Resource Include="Resources\ImageResizer.png" /> <Resource Include="Resources\ImageResizer.png" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="MahApps.Metro" Version="2.3.3" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.0"> <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.0">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.19" /> <PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.19" />
<PackageReference Include="ModernWpfUI" Version="0.9.2" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118"> <PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>

View File

@@ -0,0 +1,29 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:markup="clr-namespace:MahApps.Metro.Markup;assembly=MahApps.Metro"
xmlns:markupWithAssembly="clr-namespace:MahApps.Metro.Markup;assembly=MahApps.Metro"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:options="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:system="clr-namespace:System;assembly=System.Runtime"
mc:Ignorable="options">
<!-- Metadata -->
<system:String x:Key="Theme.Name">Dark.Accent1</system:String>
<system:String x:Key="Theme.Origin">PowerToysImageResizer</system:String>
<system:String x:Key="Theme.DisplayName">Accent1 (Dark)</system:String>
<system:String x:Key="Theme.BaseColorScheme">Dark</system:String>
<system:String x:Key="Theme.ColorScheme">Accent1</system:String>
<Color x:Key="Theme.PrimaryAccentColor">Black</Color>
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FF3a3a3a" />
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FF333333" />
<SolidColorBrush x:Key="WindowBorderBrush" Color="#FF535353"/>
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF9a9a9a"/>
<SolidColorBrush x:Key="ListViewPointerOverBrush" Color="#FF242424"/>
<SolidColorBrush x:Key="ListViewPressedBrush" Color="#FF333333"/>
<SolidColorBrush x:Key="ColorControlBackgroundBrush" Color="#FF454545"/>
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FFFFFFFF" />
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF6b6b6b" />
</ResourceDictionary>

View File

@@ -0,0 +1,29 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:markup="clr-namespace:MahApps.Metro.Markup;assembly=MahApps.Metro"
xmlns:markupWithAssembly="clr-namespace:MahApps.Metro.Markup;assembly=MahApps.Metro"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:options="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:system="clr-namespace:System;assembly=System.Runtime"
mc:Ignorable="options">
<!-- Metadata -->
<system:String x:Key="Theme.Name">HighContrast.Accent2</system:String>
<system:String x:Key="Theme.Origin">PowerToysImageResizer</system:String>
<system:String x:Key="Theme.DisplayName">Accent2 (HighContrast)</system:String>
<system:String x:Key="Theme.BaseColorScheme">HighContrast</system:String>
<system:String x:Key="Theme.ColorScheme">Accent2</system:String>
<Color x:Key="Theme.PrimaryAccentColor">White</Color>
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FF3a3a3a" />
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FF333333" />
<SolidColorBrush x:Key="WindowBorderBrush" Color="#FFffff00"/>
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF9a9a9a"/>
<SolidColorBrush x:Key="ListViewPointerOverBrush" Color="#FF242424"/>
<SolidColorBrush x:Key="ListViewPressedBrush" Color="#FF333333"/>
<SolidColorBrush x:Key="ColorControlBackgroundBrush" Color="#FF454545"/>
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FFffff00" />
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF00ff00" />
</ResourceDictionary>

View File

@@ -0,0 +1,30 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:markup="clr-namespace:MahApps.Metro.Markup;assembly=MahApps.Metro"
xmlns:markupWithAssembly="clr-namespace:MahApps.Metro.Markup;assembly=MahApps.Metro"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:options="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:system="clr-namespace:System;assembly=System.Runtime"
mc:Ignorable="options">
<!-- Metadata -->
<system:String x:Key="Theme.Name">HighContrast.Accent3</system:String>
<system:String x:Key="Theme.Origin">PowerToysImageResizer</system:String>
<system:String x:Key="Theme.DisplayName">Accent3 (HighContrast)</system:String>
<system:String x:Key="Theme.BaseColorScheme">HighContrast</system:String>
<system:String x:Key="Theme.ColorScheme">Accent3</system:String>
<Color x:Key="Theme.PrimaryAccentColor">White</Color>
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FF3a3a3a" />
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FF333333" />
<SolidColorBrush x:Key="WindowBorderBrush" Color="#FF00ff00"/>
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF9a9a9a"/>
<SolidColorBrush x:Key="ListViewPointerOverBrush" Color="#FF242424"/>
<SolidColorBrush x:Key="ListViewPressedBrush" Color="#FF333333"/>
<SolidColorBrush x:Key="ColorControlBackgroundBrush" Color="#FF454545"/>
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FF00ff00" />
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FFc0c0c0" />
</ResourceDictionary>

View File

@@ -0,0 +1,30 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:markup="clr-namespace:MahApps.Metro.Markup;assembly=MahApps.Metro"
xmlns:markupWithAssembly="clr-namespace:MahApps.Metro.Markup;assembly=MahApps.Metro"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:options="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:system="clr-namespace:System;assembly=System.Runtime"
mc:Ignorable="options">
<!-- Metadata -->
<system:String x:Key="Theme.Name">HighContrast.Accent4</system:String>
<system:String x:Key="Theme.Origin">PowerToysImageResizer</system:String>
<system:String x:Key="Theme.DisplayName">Accent4 (HighContrast)</system:String>
<system:String x:Key="Theme.BaseColorScheme">HighContrast</system:String>
<system:String x:Key="Theme.ColorScheme">Accent4</system:String>
<Color x:Key="Theme.PrimaryAccentColor">White</Color>
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FF3a3a3a" />
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FF333333" />
<SolidColorBrush x:Key="WindowBorderBrush" Color="#FFffffff"/>
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF9a9a9a"/>
<SolidColorBrush x:Key="ListViewPointerOverBrush" Color="#FF242424"/>
<SolidColorBrush x:Key="ListViewPressedBrush" Color="#FF333333"/>
<SolidColorBrush x:Key="ColorControlBackgroundBrush" Color="#FF454545"/>
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FFffffff" />
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF1aebff" />
</ResourceDictionary>

View File

@@ -0,0 +1,30 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:markup="clr-namespace:MahApps.Metro.Markup;assembly=MahApps.Metro"
xmlns:markupWithAssembly="clr-namespace:MahApps.Metro.Markup;assembly=MahApps.Metro"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:options="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:system="clr-namespace:System;assembly=System.Runtime"
mc:Ignorable="options">
<!-- Metadata -->
<system:String x:Key="Theme.Name">HighContrast.Accent5</system:String>
<system:String x:Key="Theme.Origin">PowerToysImageResizer</system:String>
<system:String x:Key="Theme.DisplayName">Accent5 (HighContrast)</system:String>
<system:String x:Key="Theme.BaseColorScheme">HighContrast</system:String>
<system:String x:Key="Theme.ColorScheme">Accent5</system:String>
<Color x:Key="Theme.PrimaryAccentColor">White</Color>
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FFededed" />
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FFe5e5e5" />
<SolidColorBrush x:Key="WindowBorderBrush" Color="Black"/>
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF949494"/>
<SolidColorBrush x:Key="ListViewPointerOverBrush" Color="#e9e9e9"/>
<SolidColorBrush x:Key="ListViewPressedBrush" Color="#FFe5e5e5"/>
<SolidColorBrush x:Key="ColorControlBackgroundBrush" Color="#FFf9f9f9"/>
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FF000000" />
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF37006e" />
</ResourceDictionary>

View File

@@ -0,0 +1,30 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:markup="clr-namespace:MahApps.Metro.Markup;assembly=MahApps.Metro"
xmlns:markupWithAssembly="clr-namespace:MahApps.Metro.Markup;assembly=MahApps.Metro"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:options="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:system="clr-namespace:System;assembly=System.Runtime"
mc:Ignorable="options">
<!-- Metadata -->
<system:String x:Key="Theme.Name">Light.Accent1</system:String>
<system:String x:Key="Theme.Origin">PowerToysImageResizer</system:String>
<system:String x:Key="Theme.DisplayName">Accent1 (Light)</system:String>
<system:String x:Key="Theme.BaseColorScheme">Light</system:String>
<system:String x:Key="Theme.ColorScheme">Accent1</system:String>
<Color x:Key="Theme.PrimaryAccentColor">White</Color>
<SolidColorBrush x:Key="SecondaryBackgroundBrush" Color="#FFededed" />
<SolidColorBrush x:Key="PrimaryBackgroundBrush" Color="#FFe5e5e5" />
<SolidColorBrush x:Key="WindowBorderBrush" Color="#FFf7f7f7"/>
<SolidColorBrush x:Key="TitleBarSecondaryForegroundBrush" Color="#FF949494"/>
<SolidColorBrush x:Key="ListViewPointerOverBrush" Color="#e9e9e9"/>
<SolidColorBrush x:Key="ListViewPressedBrush" Color="#FFe5e5e5"/>
<SolidColorBrush x:Key="ColorControlBackgroundBrush" Color="#FFf9f9f9"/>
<SolidColorBrush x:Key="PrimaryForegroundBrush" Color="#FF000000" />
<SolidColorBrush x:Key="SecondaryForegroundBrush" Color="#FF949494" />
</ResourceDictionary>

View File

@@ -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,
}
}

View File

@@ -6,7 +6,7 @@
xmlns:p="clr-namespace:ImageResizer.Properties" xmlns:p="clr-namespace:ImageResizer.Properties"
MinWidth="350"> MinWidth="350">
<StackPanel> <StackPanel Background="{DynamicResource PrimaryBackgroundBrush}">
<TextBlock Margin="11,11,11,0" <TextBlock Margin="11,11,11,0"
Style="{StaticResource MainInstructionTextBlockStyle}" Style="{StaticResource MainInstructionTextBlockStyle}"
Text="{x:Static p:Resources.Input_MainInstruction}"/> Text="{x:Static p:Resources.Input_MainInstruction}"/>