完善标题栏皮肤颜色切换

This commit is contained in:
ww-rm
2025-10-03 23:45:35 +08:00
parent 1f6e19e544
commit c9730e1a11
13 changed files with 166 additions and 19 deletions

View File

@@ -1,6 +1,7 @@
using Microsoft.Win32;
using NLog;
using SpineViewer.Natives;
using SpineViewer.Resources;
using SpineViewer.ViewModels.MainWindow;
using SpineViewer.Views;
using System.Collections.Frozen;
@@ -12,6 +13,7 @@ using System.IO;
using System.IO.Pipes;
using System.Reflection;
using System.Windows;
using System.Windows.Interop;
namespace SpineViewer
{
@@ -231,8 +233,8 @@ namespace SpineViewer
}
catch (Exception ex)
{
_logger.Error("Failed to query autorun registry key, {0}", ex.Message);
_logger.Trace(ex.ToString());
_logger.Error("Failed to query autorun registry key, {0}", ex.Message);
return false;
}
}
@@ -259,8 +261,8 @@ namespace SpineViewer
}
catch (Exception ex)
{
_logger.Error("Failed to set autorun registry key, {0}", ex.Message);
_logger.Trace(ex.ToString());
_logger.Error("Failed to set autorun registry key, {0}", ex.Message);
}
}
}
@@ -343,8 +345,8 @@ namespace SpineViewer
}
catch (Exception ex)
{
_logger.Error("Failed to switch language to {0}, {1}", value, ex.Message);
_logger.Trace(ex.ToString());
_logger.Error("Failed to switch language to {0}, {1}", value, ex.Message);
}
}
}
@@ -360,17 +362,19 @@ namespace SpineViewer
{
Resources.MergedDictionaries.Add(new() { Source = new(uri, UriKind.Relative) });
Resources.MergedDictionaries.Add(new() { Source = new("Resources/Theme.xaml", UriKind.Relative) });
var hwnd = new WindowInteropHelper(Current.MainWindow).Handle;
Dwmapi.SetWindowTextColor(hwnd, AppResource.Color_PrimaryText);
Dwmapi.SetWindowCaptionColor(hwnd, AppResource.Color_Region);
_skin = value;
}
catch (Exception ex)
{
_logger.Error("Failed to switch skin to {0}, {1}", value, ex.Message);
_logger.Trace(ex.ToString());
_logger.Error("Failed to switch skin to {0}, {1}", value, ex.Message);
}
}
}
private AppSkin _skin = AppSkin.Light;
}
public enum AppLanguage

View File

@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
namespace SpineViewer.Natives
{
/// <summary>
/// dwmapi.dll 包装类
/// </summary>
public static class Dwmapi
{
private const uint DWMWA_USE_IMMERSIVE_DARK_MODE = 20;
private const uint DWMWA_CAPTION_COLOR = 35;
private const uint DWMWA_TEXT_COLOR = 36;
private const uint DWMWA_COLOR_DEFAULT = 0xFFFFFFFF;
[DllImport("dwmapi.dll")]
private static extern int DwmSetWindowAttribute(IntPtr hwnd, uint dwAttribute, ref int pvAttribute, int cbAttribute);
[DllImport("dwmapi.dll")]
private static extern int DwmSetWindowAttribute(IntPtr hwnd, uint dwAttribute, ref uint pvAttribute, int cbAttribute);
public static bool SetWindowCaptionColor(IntPtr hwnd, Color color)
{
int c = color.R | (color.G << 8) | (color.B << 16);
return 0 == DwmSetWindowAttribute(hwnd, DWMWA_CAPTION_COLOR, ref c, sizeof(uint));
}
public static bool SetWindowTextColor(IntPtr hwnd, Color color)
{
int c = color.R | (color.G << 8) | (color.B << 16);
return 0 == DwmSetWindowAttribute(hwnd, DWMWA_TEXT_COLOR, ref c, sizeof(uint));
}
public static bool SetWindowDarkMode(IntPtr hwnd, bool darkMode)
{
int b = darkMode ? 1 : 0;
uint c = DWMWA_COLOR_DEFAULT;
DwmSetWindowAttribute(hwnd, DWMWA_CAPTION_COLOR, ref c, sizeof(uint));
DwmSetWindowAttribute(hwnd, DWMWA_TEXT_COLOR, ref c, sizeof(uint));
return 0 == DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, ref b, sizeof(int));
}
}
}

View File

@@ -66,8 +66,8 @@ namespace SpineViewer.Utils
}
catch (Exception ex)
{
_logger.Error("Failed to read json file {0}, {1}", path, ex.Message);
_logger.Trace(ex.ToString());
_logger.Error("Failed to read json file {0}, {1}", path, ex.Message);
MessagePopupService.Error($"Failed to read json file {path}, {ex.ToString()}");
}
}
@@ -88,8 +88,8 @@ namespace SpineViewer.Utils
}
catch (Exception ex)
{
_logger.Error("Failed to save json file {0}, {1}", path, ex.Message);
_logger.Trace(ex.ToString());
_logger.Error("Failed to save json file {0}, {1}", path, ex.Message);
MessagePopupService.Error($"Failed to save json file {path}, {ex.ToString()}");
return false;
}

View File

@@ -218,8 +218,8 @@ namespace SpineViewer.ViewModels.MainWindow
}
catch (Exception ex)
{
_logger.Error("Failed to reload spine {0}, {1}", sp.SkelPath, ex.Message);
_logger.Trace(ex.ToString());
_logger.Error("Failed to reload spine {0}, {1}", sp.SkelPath, ex.Message);
}
}
}
@@ -279,8 +279,8 @@ namespace SpineViewer.ViewModels.MainWindow
catch (Exception ex)
{
error++;
_logger.Error("Failed to reload spine {0}, {1}", sp.SkelPath, ex.Message);
_logger.Trace(ex.ToString());
_logger.Error("Failed to reload spine {0}, {1}", sp.SkelPath, ex.Message);
}
}
}

View File

@@ -1,4 +1,6 @@
using System;
using SpineViewer.Natives;
using SpineViewer.Resources;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -8,6 +10,7 @@ using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
@@ -22,6 +25,14 @@ namespace SpineViewer.Views
public AboutDialog()
{
InitializeComponent();
SourceInitialized += AboutDialog_SourceInitialized;
}
private void AboutDialog_SourceInitialized(object? sender, EventArgs e)
{
var hwnd = new WindowInteropHelper(this).Handle;
Dwmapi.SetWindowTextColor(hwnd, AppResource.Color_PrimaryText);
Dwmapi.SetWindowCaptionColor(hwnd, AppResource.Color_Region);
}
}
}

View File

@@ -1,4 +1,6 @@
using System;
using SpineViewer.Natives;
using SpineViewer.Resources;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -8,6 +10,7 @@ using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
@@ -22,6 +25,14 @@ namespace SpineViewer.Views
public DiagnosticsDialog()
{
InitializeComponent();
SourceInitialized += DiagnosticsDialog_SourceInitialized;
}
private void DiagnosticsDialog_SourceInitialized(object? sender, EventArgs e)
{
var hwnd = new WindowInteropHelper(this).Handle;
Dwmapi.SetWindowTextColor(hwnd, AppResource.Color_PrimaryText);
Dwmapi.SetWindowCaptionColor(hwnd, AppResource.Color_Region);
}
}
}

View File

@@ -1,4 +1,6 @@
using SpineViewer.Services;
using SpineViewer.Natives;
using SpineViewer.Resources;
using SpineViewer.Services;
using SpineViewer.ViewModels.Exporters;
using System;
using System.Collections.Generic;
@@ -10,6 +12,7 @@ using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
@@ -24,6 +27,14 @@ namespace SpineViewer.Views.ExporterDialogs
public CustomFFmpegExporterDialog()
{
InitializeComponent();
SourceInitialized += CustomFFmpegExporterDialog_SourceInitialized;
}
private void CustomFFmpegExporterDialog_SourceInitialized(object? sender, EventArgs e)
{
var hwnd = new WindowInteropHelper(this).Handle;
Dwmapi.SetWindowTextColor(hwnd, AppResource.Color_PrimaryText);
Dwmapi.SetWindowCaptionColor(hwnd, AppResource.Color_Region);
}
private void ButtonOK_Click(object sender, RoutedEventArgs e)

View File

@@ -1,4 +1,6 @@
using SpineViewer.Services;
using SpineViewer.Natives;
using SpineViewer.Resources;
using SpineViewer.Services;
using SpineViewer.ViewModels.Exporters;
using System;
using System.Collections.Generic;
@@ -10,6 +12,7 @@ using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
@@ -24,6 +27,14 @@ namespace SpineViewer.Views.ExporterDialogs
public FFmpegVideoExporterDialog()
{
InitializeComponent();
SourceInitialized += FFmpegVideoExporterDialog_SourceInitialized;
}
private void FFmpegVideoExporterDialog_SourceInitialized(object? sender, EventArgs e)
{
var hwnd = new WindowInteropHelper(this).Handle;
Dwmapi.SetWindowTextColor(hwnd, AppResource.Color_PrimaryText);
Dwmapi.SetWindowCaptionColor(hwnd, AppResource.Color_Region);
}
private void ButtonOK_Click(object sender, RoutedEventArgs e)

View File

@@ -1,4 +1,6 @@
using SpineViewer.Services;
using SpineViewer.Natives;
using SpineViewer.Resources;
using SpineViewer.Services;
using SpineViewer.ViewModels.Exporters;
using System;
using System.Collections.Generic;
@@ -10,6 +12,7 @@ using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
@@ -24,6 +27,14 @@ namespace SpineViewer.Views.ExporterDialogs
public FrameExporterDialog()
{
InitializeComponent();
SourceInitialized += FrameExporterDialog_SourceInitialized;
}
private void FrameExporterDialog_SourceInitialized(object? sender, EventArgs e)
{
var hwnd = new WindowInteropHelper(this).Handle;
Dwmapi.SetWindowTextColor(hwnd, AppResource.Color_PrimaryText);
Dwmapi.SetWindowCaptionColor(hwnd, AppResource.Color_Region);
}
private void ButtonOK_Click(object sender, RoutedEventArgs e)

View File

@@ -1,4 +1,6 @@
using SpineViewer.Services;
using SpineViewer.Natives;
using SpineViewer.Resources;
using SpineViewer.Services;
using SpineViewer.ViewModels.Exporters;
using System;
using System.Collections.Generic;
@@ -10,6 +12,7 @@ using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
@@ -24,6 +27,14 @@ namespace SpineViewer.Views.ExporterDialogs
public FrameSequenceExporterDialog()
{
InitializeComponent();
SourceInitialized += FrameSequenceExporterDialog_SourceInitialized;
}
private void FrameSequenceExporterDialog_SourceInitialized(object? sender, EventArgs e)
{
var hwnd = new WindowInteropHelper(this).Handle;
Dwmapi.SetWindowTextColor(hwnd, AppResource.Color_PrimaryText);
Dwmapi.SetWindowCaptionColor(hwnd, AppResource.Color_Region);
}
private void ButtonOK_Click(object sender, RoutedEventArgs e)

View File

@@ -15,6 +15,7 @@ using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Reflection.Metadata;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Controls;
@@ -65,11 +66,11 @@ public partial class MainWindow : Window
// XXX: hc 的 NotifyIcon 的 Text 似乎没法双向绑定
_notifyIcon.Text = _vm.Title;
SourceInitialized += MainWindow_SourceInitialized;
Loaded += MainWindow_Loaded;
ContentRendered += MainWindow_ContentRendered;
Closing += MainWindow_Closing;
Closed += MainWindow_Closed;
_vm.SpineObjectListViewModel.RequestSelectionChanging += SpinesListView_RequestSelectionChanging;
_vm.SFMLRendererViewModel.RequestSelectionChanging += SpinesListView_RequestSelectionChanging;
@@ -178,6 +179,13 @@ public partial class MainWindow : Window
#region MainWindow
private void MainWindow_SourceInitialized(object? sender, EventArgs e)
{
var hwnd = new WindowInteropHelper(this).Handle;
Dwmapi.SetWindowTextColor(hwnd, AppResource.Color_PrimaryText);
Dwmapi.SetWindowCaptionColor(hwnd, AppResource.Color_Region);
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
var vm = _vm.SFMLRendererViewModel;
@@ -728,6 +736,7 @@ public partial class MainWindow : Window
}
#endregion
private void DebugMenuItem_Click(object sender, RoutedEventArgs e)
{
@@ -737,7 +746,6 @@ public partial class MainWindow : Window
_logger.Warn("Warn");
_logger.Error("Error");
_logger.Fatal("Fatal");
return;
#endif
}

View File

@@ -1,4 +1,6 @@
using SpineViewer.Services;
using SpineViewer.Natives;
using SpineViewer.Resources;
using SpineViewer.Services;
using SpineViewer.ViewModels.Exporters;
using System;
using System.Collections.Generic;
@@ -10,6 +12,7 @@ using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
@@ -24,6 +27,14 @@ namespace SpineViewer.Views
public PreferenceDialog()
{
InitializeComponent();
SourceInitialized += PreferenceDialog_SourceInitialized;
}
private void PreferenceDialog_SourceInitialized(object? sender, EventArgs e)
{
var hwnd = new WindowInteropHelper(this).Handle;
Dwmapi.SetWindowTextColor(hwnd, AppResource.Color_PrimaryText);
Dwmapi.SetWindowCaptionColor(hwnd, AppResource.Color_Region);
}
private void ButtonOK_Click(object sender, RoutedEventArgs e)

View File

@@ -1,4 +1,6 @@
using SpineViewer.ViewModels;
using SpineViewer.Natives;
using SpineViewer.Resources;
using SpineViewer.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -25,9 +27,17 @@ namespace SpineViewer.Views
public ProgressDialog()
{
InitializeComponent();
SourceInitialized += ProgressDialog_SourceInitialized;
Loaded += ProgressWindow_Loaded;
}
private void ProgressDialog_SourceInitialized(object? sender, EventArgs e)
{
var hwnd = new WindowInteropHelper(this).Handle;
Dwmapi.SetWindowTextColor(hwnd, AppResource.Color_PrimaryText);
Dwmapi.SetWindowCaptionColor(hwnd, AppResource.Color_Region);
}
private void ProgressWindow_Loaded(object sender, RoutedEventArgs e)
{
var hwnd = new WindowInteropHelper(this).Handle;