diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d0bdd2..658d416 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # CHANGELOG +## v0.16.12 + +- 修复 label 控件文字显示问题 +- 增强报错日志输出 +- 增加实时帧率显示 +- 首选项增加预览画面和投影最大帧率设置,移除用户状态和工作区帧率记忆 +- 优化某些性能 + ## v0.16.11 - 增加 shift 切换缩放倍数 diff --git a/SFMLRenderer/SFMLRenderWindow.cs b/SFMLRenderer/SFMLRenderWindow.cs index ce31211..41f8327 100644 --- a/SFMLRenderer/SFMLRenderWindow.cs +++ b/SFMLRenderer/SFMLRenderWindow.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Threading; +using Win32Natives; namespace SFMLRenderer { @@ -19,6 +20,14 @@ namespace SFMLRenderer SetActive(false); _timer.Tick += (s, e) => DispatchEvents(); _timer.Start(); + + SetVisible(false); + + var handle = SystemHandle; + var exStyle = User32.GetWindowLong(handle, User32.GWL_EXSTYLE) | User32.WS_EX_LAYERED; + User32.SetWindowLong(handle, User32.GWL_EXSTYLE, exStyle); + User32.SetLayeredWindowAttributes(handle, 0, byte.MaxValue, User32.LWA_ALPHA); + RendererCreated?.Invoke(this, EventArgs.Empty); } diff --git a/SFMLRenderer/SFMLRenderer.csproj b/SFMLRenderer/SFMLRenderer.csproj index 9d047ed..f05e384 100644 --- a/SFMLRenderer/SFMLRenderer.csproj +++ b/SFMLRenderer/SFMLRenderer.csproj @@ -20,4 +20,8 @@ + + + + diff --git a/Spine/Exporters/CustomFFmpegExporter.cs b/Spine/Exporters/CustomFFmpegExporter.cs index 7f420c6..016ae49 100644 --- a/Spine/Exporters/CustomFFmpegExporter.cs +++ b/Spine/Exporters/CustomFFmpegExporter.cs @@ -92,7 +92,7 @@ namespace Spine.Exporters } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _logger.Error("Failed to export {0} {1}, {2}", _format, output, ex.Message); } } diff --git a/Spine/Exporters/FFmpegVideoExporter.cs b/Spine/Exporters/FFmpegVideoExporter.cs index b52d0ab..860e397 100644 --- a/Spine/Exporters/FFmpegVideoExporter.cs +++ b/Spine/Exporters/FFmpegVideoExporter.cs @@ -144,7 +144,7 @@ namespace Spine.Exporters } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _logger.Error("Failed to export {0} {1}, {2}", _format, output, ex.Message); } } diff --git a/Spine/Exporters/FrameSequenceExporter.cs b/Spine/Exporters/FrameSequenceExporter.cs index 9fd035a..f512bc6 100644 --- a/Spine/Exporters/FrameSequenceExporter.cs +++ b/Spine/Exporters/FrameSequenceExporter.cs @@ -47,7 +47,7 @@ namespace Spine.Exporters } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _logger.Error("Failed to save frame {0}, {1}", savePath, ex.Message); } finally diff --git a/Spine/Implementations/V21/SpineObjectData21.cs b/Spine/Implementations/V21/SpineObjectData21.cs index d4a39c4..ad009f2 100644 --- a/Spine/Implementations/V21/SpineObjectData21.cs +++ b/Spine/Implementations/V21/SpineObjectData21.cs @@ -36,7 +36,7 @@ namespace Spine.Implementations.V21 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); throw new InvalidDataException($"Failed to load atlas '{atlasPath}'"); } @@ -50,7 +50,7 @@ namespace Spine.Implementations.V21 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _skeletonData = new SkeletonBinary(_atlas).ReadSkeletonData(skelPath); } } @@ -62,7 +62,7 @@ namespace Spine.Implementations.V21 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _skeletonData = new SkeletonJson(_atlas).ReadSkeletonData(skelPath); } } @@ -70,7 +70,7 @@ namespace Spine.Implementations.V21 catch (Exception ex) { _atlas.Dispose(); - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); throw new InvalidDataException($"Failed to load skeleton file {skelPath}"); } diff --git a/Spine/Implementations/V34/SpineObjectData34.cs b/Spine/Implementations/V34/SpineObjectData34.cs index ae31a3a..174040f 100644 --- a/Spine/Implementations/V34/SpineObjectData34.cs +++ b/Spine/Implementations/V34/SpineObjectData34.cs @@ -36,7 +36,7 @@ namespace Spine.Implementations.V34 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); throw new InvalidDataException($"Failed to load atlas '{atlasPath}'"); } @@ -50,7 +50,7 @@ namespace Spine.Implementations.V34 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _skeletonData = new SkeletonBinary(_atlas).ReadSkeletonData(skelPath); } } @@ -62,7 +62,7 @@ namespace Spine.Implementations.V34 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _skeletonData = new SkeletonJson(_atlas).ReadSkeletonData(skelPath); } } @@ -70,7 +70,7 @@ namespace Spine.Implementations.V34 catch (Exception ex) { _atlas.Dispose(); - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); throw new InvalidDataException($"Failed to load skeleton file {skelPath}"); } diff --git a/Spine/Implementations/V35/SpineObjectData35.cs b/Spine/Implementations/V35/SpineObjectData35.cs index 4b29545..23a9a7e 100644 --- a/Spine/Implementations/V35/SpineObjectData35.cs +++ b/Spine/Implementations/V35/SpineObjectData35.cs @@ -36,7 +36,7 @@ namespace Spine.Implementations.V35 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); throw new InvalidDataException($"Failed to load atlas '{atlasPath}'"); } @@ -50,7 +50,7 @@ namespace Spine.Implementations.V35 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _skeletonData = new SkeletonBinary(_atlas).ReadSkeletonData(skelPath); } } @@ -62,7 +62,7 @@ namespace Spine.Implementations.V35 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _skeletonData = new SkeletonJson(_atlas).ReadSkeletonData(skelPath); } } @@ -70,7 +70,7 @@ namespace Spine.Implementations.V35 catch (Exception ex) { _atlas.Dispose(); - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); throw new InvalidDataException($"Failed to load skeleton file {skelPath}"); } diff --git a/Spine/Implementations/V36/SpineObjectData36.cs b/Spine/Implementations/V36/SpineObjectData36.cs index e7846f7..96cbdef 100644 --- a/Spine/Implementations/V36/SpineObjectData36.cs +++ b/Spine/Implementations/V36/SpineObjectData36.cs @@ -36,7 +36,7 @@ namespace Spine.Implementations.V36 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); throw new InvalidDataException($"Failed to load atlas '{atlasPath}'"); } @@ -50,7 +50,7 @@ namespace Spine.Implementations.V36 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _skeletonData = new SkeletonBinary(_atlas).ReadSkeletonData(skelPath); } } @@ -62,7 +62,7 @@ namespace Spine.Implementations.V36 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _skeletonData = new SkeletonJson(_atlas).ReadSkeletonData(skelPath); } } @@ -70,7 +70,7 @@ namespace Spine.Implementations.V36 catch (Exception ex) { _atlas.Dispose(); - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); throw new InvalidDataException($"Failed to load skeleton file {skelPath}"); } diff --git a/Spine/Implementations/V37/SpineObjectData37.cs b/Spine/Implementations/V37/SpineObjectData37.cs index b8674b2..db5ce65 100644 --- a/Spine/Implementations/V37/SpineObjectData37.cs +++ b/Spine/Implementations/V37/SpineObjectData37.cs @@ -36,7 +36,7 @@ namespace Spine.Implementations.V37 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); throw new InvalidDataException($"Failed to load atlas '{atlasPath}'"); } @@ -50,7 +50,7 @@ namespace Spine.Implementations.V37 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _skeletonData = new SkeletonBinary(_atlas).ReadSkeletonData(skelPath); } } @@ -62,7 +62,7 @@ namespace Spine.Implementations.V37 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _skeletonData = new SkeletonJson(_atlas).ReadSkeletonData(skelPath); } } @@ -70,7 +70,7 @@ namespace Spine.Implementations.V37 catch (Exception ex) { _atlas.Dispose(); - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); throw new InvalidDataException($"Failed to load skeleton file {skelPath}"); } diff --git a/Spine/Implementations/V38/SpineObjectData38.cs b/Spine/Implementations/V38/SpineObjectData38.cs index 680d43c..e1069de 100644 --- a/Spine/Implementations/V38/SpineObjectData38.cs +++ b/Spine/Implementations/V38/SpineObjectData38.cs @@ -37,7 +37,7 @@ namespace Spine.Implementations.V38 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); throw new InvalidDataException($"Failed to load atlas '{atlasPath}'"); } @@ -51,7 +51,7 @@ namespace Spine.Implementations.V38 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _skeletonData = new SkeletonBinary(_atlas).ReadSkeletonData(skelPath); } } @@ -63,7 +63,7 @@ namespace Spine.Implementations.V38 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _skeletonData = new SkeletonJson(_atlas).ReadSkeletonData(skelPath); } } @@ -71,7 +71,7 @@ namespace Spine.Implementations.V38 catch (Exception ex) { _atlas.Dispose(); - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); throw new InvalidDataException($"Failed to load skeleton file {skelPath}"); } diff --git a/Spine/Implementations/V40/SpineObjectData40.cs b/Spine/Implementations/V40/SpineObjectData40.cs index b02a489..7df752e 100644 --- a/Spine/Implementations/V40/SpineObjectData40.cs +++ b/Spine/Implementations/V40/SpineObjectData40.cs @@ -36,7 +36,7 @@ namespace Spine.Implementations.V40 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); throw new InvalidDataException($"Failed to load atlas '{atlasPath}'"); } @@ -50,7 +50,7 @@ namespace Spine.Implementations.V40 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _skeletonData = new SkeletonBinary(_atlas).ReadSkeletonData(skelPath); } } @@ -62,7 +62,7 @@ namespace Spine.Implementations.V40 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _skeletonData = new SkeletonJson(_atlas).ReadSkeletonData(skelPath); } } @@ -70,7 +70,7 @@ namespace Spine.Implementations.V40 catch (Exception ex) { _atlas.Dispose(); - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); throw new InvalidDataException($"Failed to load skeleton file {skelPath}"); } diff --git a/Spine/Implementations/V41/SpineObjectData41.cs b/Spine/Implementations/V41/SpineObjectData41.cs index 25ede0d..b1ec552 100644 --- a/Spine/Implementations/V41/SpineObjectData41.cs +++ b/Spine/Implementations/V41/SpineObjectData41.cs @@ -36,7 +36,7 @@ namespace Spine.Implementations.V41 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); throw new InvalidDataException($"Failed to load atlas '{atlasPath}'"); } @@ -50,7 +50,7 @@ namespace Spine.Implementations.V41 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _skeletonData = new SkeletonBinary(_atlas).ReadSkeletonData(skelPath); } } @@ -62,7 +62,7 @@ namespace Spine.Implementations.V41 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _skeletonData = new SkeletonJson(_atlas).ReadSkeletonData(skelPath); } } @@ -70,7 +70,7 @@ namespace Spine.Implementations.V41 catch (Exception ex) { _atlas.Dispose(); - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); throw new InvalidDataException($"Failed to load skeleton file {skelPath}"); } diff --git a/Spine/Implementations/V42/SpineObjectData42.cs b/Spine/Implementations/V42/SpineObjectData42.cs index 95afa35..5a07967 100644 --- a/Spine/Implementations/V42/SpineObjectData42.cs +++ b/Spine/Implementations/V42/SpineObjectData42.cs @@ -36,7 +36,7 @@ namespace Spine.Implementations.V42 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); throw new InvalidDataException($"Failed to load atlas '{atlasPath}'"); } @@ -50,7 +50,7 @@ namespace Spine.Implementations.V42 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _skeletonData = new SkeletonBinary(_atlas).ReadSkeletonData(skelPath); } } @@ -62,7 +62,7 @@ namespace Spine.Implementations.V42 } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _skeletonData = new SkeletonJson(_atlas).ReadSkeletonData(skelPath); } } @@ -70,7 +70,7 @@ namespace Spine.Implementations.V42 catch (Exception ex) { _atlas.Dispose(); - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); throw new InvalidDataException($"Failed to load skeleton file {skelPath}"); } diff --git a/Spine/SpineExtension.cs b/Spine/SpineExtension.cs index 9d04db8..c8bc5a6 100644 --- a/Spine/SpineExtension.cs +++ b/Spine/SpineExtension.cs @@ -269,7 +269,7 @@ namespace Spine if (hit && LogHitSlots) { - _logger.Debug("Hit ({0}): [{1}]", self.Name, hitSlotName); + _logger.Info("Hit ({0}): [{1}]", self.Name, hitSlotName); } return hit; } diff --git a/Spine/SpineObject.cs b/Spine/SpineObject.cs index c911521..f1aef2d 100644 --- a/Spine/SpineObject.cs +++ b/Spine/SpineObject.cs @@ -82,7 +82,7 @@ namespace Spine } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _logger.Warn("Failed to detect version for skel {0}, try all available versions", skelPath); } } @@ -118,7 +118,7 @@ namespace Spine } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); throw new InvalidDataException($"Failed to load spine with version '{version}'"); } } diff --git a/SpineViewer.sln b/SpineViewer.sln index cb6c58c..9cb9c0c 100644 --- a/SpineViewer.sln +++ b/SpineViewer.sln @@ -43,6 +43,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpineRuntime35", "SpineRunt EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpineRuntime34", "SpineRuntimes\SpineRuntime34\SpineRuntime34.csproj", "{348605F7-3FF4-1DE0-4B91-7AEFE7BC5C55}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Win32Natives", "Win32Natives\Win32Natives.csproj", "{48864874-7307-950E-A667-62BB66357C62}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -105,6 +107,10 @@ Global {348605F7-3FF4-1DE0-4B91-7AEFE7BC5C55}.Debug|x64.Build.0 = Debug|x64 {348605F7-3FF4-1DE0-4B91-7AEFE7BC5C55}.Release|x64.ActiveCfg = Release|x64 {348605F7-3FF4-1DE0-4B91-7AEFE7BC5C55}.Release|x64.Build.0 = Release|x64 + {48864874-7307-950E-A667-62BB66357C62}.Debug|x64.ActiveCfg = Debug|x64 + {48864874-7307-950E-A667-62BB66357C62}.Debug|x64.Build.0 = Debug|x64 + {48864874-7307-950E-A667-62BB66357C62}.Release|x64.ActiveCfg = Release|x64 + {48864874-7307-950E-A667-62BB66357C62}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/SpineViewer/App.xaml.cs b/SpineViewer/App.xaml.cs index 9baa531..dd403ee 100644 --- a/SpineViewer/App.xaml.cs +++ b/SpineViewer/App.xaml.cs @@ -1,7 +1,8 @@ using Microsoft.Win32; using NLog; -using SpineViewer.Natives; +using Win32Natives; using SpineViewer.Resources; +using SpineViewer.Services; using SpineViewer.ViewModels.MainWindow; using SpineViewer.Views; using System.Collections.Frozen; @@ -14,6 +15,7 @@ using System.IO.Pipes; using System.Reflection; using System.Windows; using System.Windows.Interop; +using SpineViewer.Extensions; namespace SpineViewer { @@ -33,8 +35,8 @@ namespace SpineViewer #endif public const string AutoRunFlag = "--autorun"; - private const string MutexName = "__SpineViewerInstance__"; - private const string PipeName = "__SpineViewerPipe__"; + private const string MutexName = $"__{AppName}_Instance__"; + private const string PipeName = $"_{AppName}_Pipe__"; public static readonly string ProcessPath = Environment.ProcessPath; public static readonly string ProcessDirectory = Path.GetDirectoryName(Environment.ProcessPath); @@ -58,13 +60,16 @@ namespace SpineViewer AppDomain.CurrentDomain.UnhandledException += (s, e) => { + _logger.Debug(e.ExceptionObject.ToString()); _logger.Fatal("Unhandled exception: {0}", e.ExceptionObject); + MessagePopupService.Error(e.ExceptionObject.ToString()); }; TaskScheduler.UnobservedTaskException += (s, e) => { - _logger.Trace(e.Exception.ToString()); - _logger.Error("Unobserved task exception: {0}", e.Exception.Message); + _logger.Debug(e.Exception.ToString()); + _logger.Fatal("Unobserved task exception: {0}", e.Exception.Message); e.SetObserved(); + MessagePopupService.Error(e.Exception.ToString()); }; // 单例模式加 IPC 通信 @@ -130,7 +135,7 @@ namespace SpineViewer } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _logger.Error("Failed to pass command line args to existed instance, {0}", ex.Message); } } @@ -191,7 +196,7 @@ namespace SpineViewer } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _logger.Error("Failed to process arguments, {0}", ex.Message); } } @@ -212,9 +217,10 @@ namespace SpineViewer private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) { - _logger.Trace(e.Exception.ToString()); - _logger.Error("Dispatcher unhandled exception: {0}", e.Exception.Message); + _logger.Debug(e.Exception.ToString()); + _logger.Fatal("Dispatcher unhandled exception: {0}", e.Exception.Message); e.Handled = true; + MessagePopupService.Error(e.Exception.ToString()); } public bool AutoRun @@ -231,7 +237,7 @@ namespace SpineViewer } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _logger.Error("Failed to query autorun registry key, {0}", ex.Message); return false; } @@ -259,7 +265,7 @@ namespace SpineViewer } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _logger.Error("Failed to set autorun registry key, {0}", ex.Message); } } @@ -343,7 +349,7 @@ namespace SpineViewer } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _logger.Error("Failed to switch language to {0}, {1}", value, ex.Message); } } @@ -360,14 +366,13 @@ 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); + Current.MainWindow.SetWindowTextColor(AppResource.Color_PrimaryText); + Current.MainWindow.SetWindowCaptionColor(AppResource.Color_Region); _skin = value; } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _logger.Error("Failed to switch skin to {0}, {1}", value, ex.Message); } } diff --git a/SpineViewer/Extensions/WpfExtension.cs b/SpineViewer/Extensions/WpfExtension.cs index 9ce86e0..ddfd3da 100644 --- a/SpineViewer/Extensions/WpfExtension.cs +++ b/SpineViewer/Extensions/WpfExtension.cs @@ -1,6 +1,4 @@ -using SFML.Graphics; -using SFML.System; -using SkiaSharp; +using SkiaSharp; using System; using System.Collections.Generic; using System.IO; @@ -9,29 +7,31 @@ using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows; +using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; +using Win32Natives; namespace SpineViewer.Extensions { public static class WpfExtension { - public static FloatRect ToFloatRect(this Rect self) + public static SFML.Graphics.FloatRect ToFloatRect(this Rect self) { return new((float)self.X, (float)self.Y, (float)self.Width, (float)self.Height); } - public static Vector2f ToVector2f(this Size self) + public static SFML.System.Vector2f ToVector2f(this Size self) { return new((float)self.Width, (float)self.Height); } - public static Vector2u ToVector2u(this Size self) + public static SFML.System.Vector2u ToVector2u(this Size self) { return new((uint)self.Width, (uint)self.Height); } - public static Vector2i ToVector2i(this Size self) + public static SFML.System.Vector2i ToVector2i(this Size self) { return new((int)self.Width, (int)self.Height); } @@ -60,6 +60,18 @@ namespace SpineViewer.Extensions return wb; } + public static void SetWindowTextColor(this Window self, Color color) + { + var hwnd = new WindowInteropHelper(self).Handle; + Dwmapi.SetWindowTextColor(hwnd, color.R, color.G, color.B); + } + + public static void SetWindowCaptionColor(this Window self, Color color) + { + var hwnd = new WindowInteropHelper(self).Handle; + Dwmapi.SetWindowCaptionColor(hwnd, color.R, color.G, color.B); + } + //public static void SaveToFile(this BitmapSource bitmap, string path) //{ // var ext = Path.GetExtension(path)?.ToLowerInvariant(); diff --git a/SpineViewer/Models/PreferenceModel.cs b/SpineViewer/Models/PreferenceModel.cs index 1575935..7385520 100644 --- a/SpineViewer/Models/PreferenceModel.cs +++ b/SpineViewer/Models/PreferenceModel.cs @@ -73,6 +73,22 @@ namespace SpineViewer.Models #endregion + #region 预览画面首选项 + + [ObservableProperty] + private bool _renderSelectedOnly; + + [ObservableProperty] + private HitTestLevel _hitTestLevel; + + [ObservableProperty] + private bool _logHitSlots; + + [ObservableProperty] + private uint _maxFps = 30; + + #endregion + #region 程序选项 public RelayCommand Cmd_SelectAutoRunWorkspaceConfigPath => _cmd_SelectAutoRunWorkspaceConfigPath ??= new(() => @@ -89,18 +105,12 @@ namespace SpineViewer.Models [ObservableProperty] private AppSkin _appSkin; - [ObservableProperty] - private bool _renderSelectedOnly; - - [ObservableProperty] - private HitTestLevel _hitTestLevel; - - [ObservableProperty] - private bool _logHitSlots; - [ObservableProperty] private bool _wallpaperView; + [ObservableProperty] + private uint _wallpaperMaxFps = 30; + [ObservableProperty] private bool _closeToTray; diff --git a/SpineViewer/Models/UserStateModel.cs b/SpineViewer/Models/UserStateModel.cs index 8a0d73f..6ed5643 100644 --- a/SpineViewer/Models/UserStateModel.cs +++ b/SpineViewer/Models/UserStateModel.cs @@ -43,7 +43,6 @@ namespace SpineViewer.Models public uint ResolutionX { get; set; } = 1500; public uint ResolutionY { get; set; } = 1000; - public uint MaxFps { get; set; } = 30; public float Speed { get; set; } = 1f; public bool ShowAxis { get; set; } = true; public Color BackgroundColor { get; set; } = Color.FromRgb(105, 105, 105); diff --git a/SpineViewer/Models/WorkspaceModel.cs b/SpineViewer/Models/WorkspaceModel.cs index a608cbb..7392d86 100644 --- a/SpineViewer/Models/WorkspaceModel.cs +++ b/SpineViewer/Models/WorkspaceModel.cs @@ -34,8 +34,6 @@ namespace SpineViewer.Models public bool FlipY { get; set; } = true; - public uint MaxFps { get; set; } = 30; - public float Speed { get; set; } = 1f; public bool ShowAxis { get; set; } = true; diff --git a/SpineViewer/Resources/Strings/en.xaml b/SpineViewer/Resources/Strings/en.xaml index e4bdbfd..d584489 100644 --- a/SpineViewer/Resources/Strings/en.xaml +++ b/SpineViewer/Resources/Strings/en.xaml @@ -123,6 +123,8 @@ Maximum frame rate of the preview. Set to 0 for no limit. Playback Speed Wallpaper View + Max FPS of Wallpaper View + Maximum frame rate of the wallpaper view. Set to 0 for no limit. Render Selected Only Hit Test Accuracy Level Output Hit Test Slot Names @@ -140,6 +142,9 @@ Forward 10 Frames Window/Fullscreen; F11 + + Real-time FPS: {0:F1}/{1:F1} + OK Cancel diff --git a/SpineViewer/Resources/Strings/ja.xaml b/SpineViewer/Resources/Strings/ja.xaml index 16559c7..37fb083 100644 --- a/SpineViewer/Resources/Strings/ja.xaml +++ b/SpineViewer/Resources/Strings/ja.xaml @@ -123,6 +123,8 @@ プレビュー画面の最大フレームレート。0 に設定すると制限なし。 再生速度 壁紙表示 + 壁紙ビューの最大FPS + 壁紙ビューの最大フレームレート。0に設定すると制限がなし。 選択のみレンダリング ヒットテスト精度レベル ヒットテスト結果のスロット名を出力 @@ -140,6 +142,9 @@ 10フレーム進める ウィンドウ/フルスクリーン; F11 + + リアルタイムFPS:{0:F1}/{1:F1} + OK キャンセル diff --git a/SpineViewer/Resources/Strings/zh.xaml b/SpineViewer/Resources/Strings/zh.xaml index 9fc695c..99c1523 100644 --- a/SpineViewer/Resources/Strings/zh.xaml +++ b/SpineViewer/Resources/Strings/zh.xaml @@ -123,6 +123,8 @@ 预览画面的最大帧率,设置为 0 时则无帧率限制 播放速度 桌面投影 + 桌面投影最大帧率 + 桌面投影的最大帧率,设置为 0 时则无帧率限制 仅渲染选中 命中检测准确度等级 输出命中检测结果的插槽名称 @@ -140,6 +142,9 @@ 快进 10 帧 窗口/全屏; F11 + + 实时帧率:{0:F1}/{1:F1} + 确认 取消 diff --git a/SpineViewer/Resources/Theme.xaml b/SpineViewer/Resources/Theme.xaml index fb363f5..c338f5a 100644 --- a/SpineViewer/Resources/Theme.xaml +++ b/SpineViewer/Resources/Theme.xaml @@ -11,7 +11,7 @@ - - - - - - - - + + diff --git a/SpineViewer/Views/AboutDialog.xaml.cs b/SpineViewer/Views/AboutDialog.xaml.cs index f390768..a98bc35 100644 --- a/SpineViewer/Views/AboutDialog.xaml.cs +++ b/SpineViewer/Views/AboutDialog.xaml.cs @@ -1,4 +1,4 @@ -using SpineViewer.Natives; +using SpineViewer.Extensions; using SpineViewer.Resources; using System; using System.Collections.Generic; @@ -14,6 +14,7 @@ using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; +using Win32Natives; namespace SpineViewer.Views { @@ -30,9 +31,8 @@ namespace SpineViewer.Views 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); + this.SetWindowTextColor(AppResource.Color_PrimaryText); + this.SetWindowCaptionColor(AppResource.Color_Region); } } } diff --git a/SpineViewer/Views/DiagnosticsDialog.xaml b/SpineViewer/Views/DiagnosticsDialog.xaml index ea046ad..ba58e9b 100644 --- a/SpineViewer/Views/DiagnosticsDialog.xaml +++ b/SpineViewer/Views/DiagnosticsDialog.xaml @@ -24,7 +24,7 @@ - diff --git a/SpineViewer/Views/DiagnosticsDialog.xaml.cs b/SpineViewer/Views/DiagnosticsDialog.xaml.cs index 72ca5aa..c79e895 100644 --- a/SpineViewer/Views/DiagnosticsDialog.xaml.cs +++ b/SpineViewer/Views/DiagnosticsDialog.xaml.cs @@ -1,4 +1,4 @@ -using SpineViewer.Natives; +using SpineViewer.Extensions; using SpineViewer.Resources; using System; using System.Collections.Generic; @@ -14,6 +14,7 @@ using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; +using Win32Natives; namespace SpineViewer.Views { @@ -30,9 +31,8 @@ namespace SpineViewer.Views 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); + this.SetWindowTextColor(AppResource.Color_PrimaryText); + this.SetWindowCaptionColor(AppResource.Color_Region); } } } diff --git a/SpineViewer/Views/ExporterDialogs/CustomFFmpegExporterDialog.xaml b/SpineViewer/Views/ExporterDialogs/CustomFFmpegExporterDialog.xaml index 4f2867c..53b2b65 100644 --- a/SpineViewer/Views/ExporterDialogs/CustomFFmpegExporterDialog.xaml +++ b/SpineViewer/Views/ExporterDialogs/CustomFFmpegExporterDialog.xaml @@ -31,7 +31,7 @@ - diff --git a/SpineViewer/Views/ExporterDialogs/CustomFFmpegExporterDialog.xaml.cs b/SpineViewer/Views/ExporterDialogs/CustomFFmpegExporterDialog.xaml.cs index eda8ae4..efce9e0 100644 --- a/SpineViewer/Views/ExporterDialogs/CustomFFmpegExporterDialog.xaml.cs +++ b/SpineViewer/Views/ExporterDialogs/CustomFFmpegExporterDialog.xaml.cs @@ -1,4 +1,4 @@ -using SpineViewer.Natives; +using Win32Natives; using SpineViewer.Resources; using SpineViewer.Services; using SpineViewer.ViewModels.Exporters; @@ -16,6 +16,7 @@ using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; +using SpineViewer.Extensions; namespace SpineViewer.Views.ExporterDialogs { @@ -32,9 +33,8 @@ namespace SpineViewer.Views.ExporterDialogs 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); + this.SetWindowTextColor(AppResource.Color_PrimaryText); + this.SetWindowCaptionColor(AppResource.Color_Region); } private void ButtonOK_Click(object sender, RoutedEventArgs e) diff --git a/SpineViewer/Views/ExporterDialogs/FFmpegVideoExporterDialog.xaml b/SpineViewer/Views/ExporterDialogs/FFmpegVideoExporterDialog.xaml index 91e3efa..25fbda1 100644 --- a/SpineViewer/Views/ExporterDialogs/FFmpegVideoExporterDialog.xaml +++ b/SpineViewer/Views/ExporterDialogs/FFmpegVideoExporterDialog.xaml @@ -31,7 +31,7 @@ - diff --git a/SpineViewer/Views/ExporterDialogs/FFmpegVideoExporterDialog.xaml.cs b/SpineViewer/Views/ExporterDialogs/FFmpegVideoExporterDialog.xaml.cs index b4dbaaa..9b92f6a 100644 --- a/SpineViewer/Views/ExporterDialogs/FFmpegVideoExporterDialog.xaml.cs +++ b/SpineViewer/Views/ExporterDialogs/FFmpegVideoExporterDialog.xaml.cs @@ -1,4 +1,4 @@ -using SpineViewer.Natives; +using SpineViewer.Extensions; using SpineViewer.Resources; using SpineViewer.Services; using SpineViewer.ViewModels.Exporters; @@ -16,6 +16,7 @@ using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; +using Win32Natives; namespace SpineViewer.Views.ExporterDialogs { @@ -32,9 +33,8 @@ namespace SpineViewer.Views.ExporterDialogs 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); + this.SetWindowTextColor(AppResource.Color_PrimaryText); + this.SetWindowCaptionColor(AppResource.Color_Region); } private void ButtonOK_Click(object sender, RoutedEventArgs e) diff --git a/SpineViewer/Views/ExporterDialogs/FrameExporterDialog.xaml b/SpineViewer/Views/ExporterDialogs/FrameExporterDialog.xaml index 2da3a98..f309a2a 100644 --- a/SpineViewer/Views/ExporterDialogs/FrameExporterDialog.xaml +++ b/SpineViewer/Views/ExporterDialogs/FrameExporterDialog.xaml @@ -31,7 +31,7 @@ - diff --git a/SpineViewer/Views/ExporterDialogs/FrameExporterDialog.xaml.cs b/SpineViewer/Views/ExporterDialogs/FrameExporterDialog.xaml.cs index b34058f..e29e695 100644 --- a/SpineViewer/Views/ExporterDialogs/FrameExporterDialog.xaml.cs +++ b/SpineViewer/Views/ExporterDialogs/FrameExporterDialog.xaml.cs @@ -1,4 +1,4 @@ -using SpineViewer.Natives; +using SpineViewer.Extensions; using SpineViewer.Resources; using SpineViewer.Services; using SpineViewer.ViewModels.Exporters; @@ -16,6 +16,7 @@ using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; +using Win32Natives; namespace SpineViewer.Views.ExporterDialogs { @@ -32,9 +33,8 @@ namespace SpineViewer.Views.ExporterDialogs 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); + this.SetWindowTextColor(AppResource.Color_PrimaryText); + this.SetWindowCaptionColor(AppResource.Color_Region); } private void ButtonOK_Click(object sender, RoutedEventArgs e) diff --git a/SpineViewer/Views/ExporterDialogs/FrameSequenceExporterDialog.xaml b/SpineViewer/Views/ExporterDialogs/FrameSequenceExporterDialog.xaml index 6688872..73bbb27 100644 --- a/SpineViewer/Views/ExporterDialogs/FrameSequenceExporterDialog.xaml +++ b/SpineViewer/Views/ExporterDialogs/FrameSequenceExporterDialog.xaml @@ -31,7 +31,7 @@ - diff --git a/SpineViewer/Views/ExporterDialogs/FrameSequenceExporterDialog.xaml.cs b/SpineViewer/Views/ExporterDialogs/FrameSequenceExporterDialog.xaml.cs index 1ed0c47..db4c9d4 100644 --- a/SpineViewer/Views/ExporterDialogs/FrameSequenceExporterDialog.xaml.cs +++ b/SpineViewer/Views/ExporterDialogs/FrameSequenceExporterDialog.xaml.cs @@ -1,4 +1,4 @@ -using SpineViewer.Natives; +using SpineViewer.Extensions; using SpineViewer.Resources; using SpineViewer.Services; using SpineViewer.ViewModels.Exporters; @@ -16,6 +16,7 @@ using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; +using Win32Natives; namespace SpineViewer.Views.ExporterDialogs { @@ -32,9 +33,8 @@ namespace SpineViewer.Views.ExporterDialogs 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); + this.SetWindowTextColor(AppResource.Color_PrimaryText); + this.SetWindowCaptionColor(AppResource.Color_Region); } private void ButtonOK_Click(object sender, RoutedEventArgs e) diff --git a/SpineViewer/Views/MainWindow.xaml b/SpineViewer/Views/MainWindow.xaml index 06f20bf..0a2fcfa 100644 --- a/SpineViewer/Views/MainWindow.xaml +++ b/SpineViewer/Views/MainWindow.xaml @@ -239,7 +239,7 @@ TabStripPlacement="Bottom" DataContext="{Binding SpineObjectTabViewModel}"> - @@ -695,7 +695,7 @@ - @@ -793,16 +793,6 @@ - - - - - - - - @@ -912,14 +902,16 @@ - - - - - - - - + + + + + + + + + + - @@ -1052,7 +1044,23 @@ - + + + + + + + + + + + + + + + + + diff --git a/SpineViewer/Views/MainWindow.xaml.cs b/SpineViewer/Views/MainWindow.xaml.cs index f705ca1..6844fbc 100644 --- a/SpineViewer/Views/MainWindow.xaml.cs +++ b/SpineViewer/Views/MainWindow.xaml.cs @@ -1,8 +1,8 @@ using NLog; using SFMLRenderer; using Spine; +using SpineViewer.Extensions; using SpineViewer.Models; -using SpineViewer.Natives; using SpineViewer.Resources; using SpineViewer.Services; using SpineViewer.Utils; @@ -24,6 +24,7 @@ using System.Windows.Input; using System.Windows.Interop; using System.Windows.Media; using System.Windows.Threading; +using Win32Natives; namespace SpineViewer.Views; @@ -47,7 +48,7 @@ public partial class MainWindow : Window private readonly List _userStateWatchers = []; private DispatcherTimer _saveUserStateTimer; - private readonly TimeSpan _saveTimerDelay = TimeSpan.FromSeconds(3); + private readonly TimeSpan _saveTimerDelay = TimeSpan.FromSeconds(1); public bool RootGridCol0Folded { @@ -98,13 +99,13 @@ public partial class MainWindow : Window // Initialize Wallpaper RenderWindow _wallpaperRenderWindow = new(new(1, 1), "SpineViewerWallpaper", SFML.Window.Styles.None); - _wallpaperRenderWindow.SetVisible(false); + _wallpaperRenderWindow.MaxFps = 30; + var handle = _wallpaperRenderWindow.SystemHandle; var style = User32.GetWindowLong(handle, User32.GWL_STYLE) | User32.WS_POPUP; - var exStyle = User32.GetWindowLong(handle, User32.GWL_EXSTYLE) | User32.WS_EX_LAYERED | User32.WS_EX_TOOLWINDOW; + var exStyle = User32.GetWindowLong(handle, User32.GWL_EXSTYLE) | User32.WS_EX_TOOLWINDOW; User32.SetWindowLong(handle, User32.GWL_STYLE, style); User32.SetWindowLong(handle, User32.GWL_EXSTYLE, exStyle); - User32.SetLayeredWindowAttributes(handle, 0, byte.MaxValue, User32.LWA_ALPHA); DataContext = _vm = new(_renderPanel, _wallpaperRenderWindow); @@ -153,9 +154,8 @@ public partial class MainWindow : Window 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); + this.SetWindowTextColor(AppResource.Color_PrimaryText); + this.SetWindowCaptionColor(AppResource.Color_Region); } private void MainWindow_Loaded(object sender, RoutedEventArgs e) @@ -274,7 +274,6 @@ public partial class MainWindow : Window _vm.ExplorerListViewModel.CurrentDirectory = m.ExploringDirectory; _vm.SFMLRendererViewModel.SetResolution(m.ResolutionX, m.ResolutionY); - _vm.SFMLRendererViewModel.MaxFps = m.MaxFps; _vm.SFMLRendererViewModel.Speed = m.Speed; _vm.SFMLRendererViewModel.ShowAxis = m.ShowAxis; _vm.SFMLRendererViewModel.BackgroundColor = m.BackgroundColor; @@ -310,7 +309,6 @@ public partial class MainWindow : Window ResolutionX = _vm.SFMLRendererViewModel.ResolutionX, ResolutionY = _vm.SFMLRendererViewModel.ResolutionY, - MaxFps = _vm.SFMLRendererViewModel.MaxFps, Speed = _vm.SFMLRendererViewModel.Speed, ShowAxis = _vm.SFMLRendererViewModel.ShowAxis, BackgroundColor = _vm.SFMLRendererViewModel.BackgroundColor, @@ -400,7 +398,6 @@ public partial class MainWindow : Window { case nameof(SFMLRendererViewModel.ResolutionX): case nameof(SFMLRendererViewModel.ResolutionY): - case nameof(SFMLRendererViewModel.MaxFps): case nameof(SFMLRendererViewModel.Speed): case nameof(SFMLRendererViewModel.ShowAxis): case nameof(SFMLRendererViewModel.BackgroundColor): @@ -440,6 +437,7 @@ public partial class MainWindow : Window private void SFMLRendererViewModel_PropertyChanged(object? sender, PropertyChangedEventArgs e) { + // XXX: 资源管理器重启后窗口会有问题无法重新显示, 需要重启应用, 否则要重新创建窗口 if (e.PropertyName == nameof(SFMLRendererViewModel.WallpaperView)) { var wnd = _wallpaperRenderWindow; @@ -451,17 +449,25 @@ public partial class MainWindow : Window _logger.Error("Failed to enable wallpaper view, WorkerW not found"); return; } - var handle = wnd.SystemHandle; User32.GetPrimaryScreenResolution(out var sw, out var sh); + _vm.SFMLRendererViewModel.SetResolution(sw, sh); - User32.SetParent(handle, workerw); + var handle = wnd.SystemHandle; + + // 每次都进行设置, 确保会成为顶层子窗口 + var lastParent = User32.SetParent(handle, workerw); + Debug.WriteLine($"0x{lastParent:x8} = SetParent(0x{handle:x8}, 0x{workerw:x8})"); User32.SetLayeredWindowAttributes(handle, 0, byte.MaxValue, User32.LWA_ALPHA); - _vm.SFMLRendererViewModel.SetResolution(sw, sh); + // XXX: 每次新设置成桌面子窗口之后, 要确保窗口 Size 发生一次变化来触发 SFML 内部的渲染视图更新 + var ssize = new SFML.System.Vector2u(sw, sh); + if (lastParent != workerw && ssize == wnd.Size) + { + wnd.Size = new(sw + 1, sh); + } wnd.Position = new(0, 0); - wnd.Size = new(sw + 1, sh); - wnd.Size = new(sw, sh); + wnd.Size = ssize; wnd.SetVisible(true); } else @@ -694,7 +700,7 @@ public partial class MainWindow : Window _renderPanelButtonsPopupContainer.Child = _renderPanelButtonsPanel; _loggerBoxContainer.Child = null; - _loggerBoxPopupContainer.Child = _loggerRichTextBox; + _loggerBoxPopupContainer.Child = _loggerBoxPanel; } private void SwitchToNormalLayout() @@ -704,7 +710,7 @@ public partial class MainWindow : Window HandyControl.Controls.IconElement.SetGeometry(_fullScreenButton, AppResource.Geo_ArrowsMaximize); _loggerBoxPopupContainer.Child = null; - _loggerBoxContainer.Child = _loggerRichTextBox; + _loggerBoxContainer.Child = _loggerBoxPanel; _renderPanelButtonsPopupContainer.Child = null; _renderPanelButtonsContainer.Child = _renderPanelButtonsPanel; diff --git a/SpineViewer/Views/PreferenceDialog.xaml b/SpineViewer/Views/PreferenceDialog.xaml index 9384a2c..9bb520b 100644 --- a/SpineViewer/Views/PreferenceDialog.xaml +++ b/SpineViewer/Views/PreferenceDialog.xaml @@ -31,7 +31,7 @@ - @@ -195,30 +195,8 @@ - + - - - - - - - - - - - - - - @@ -248,6 +226,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + @@ -257,6 +270,15 @@ + + + + + + + diff --git a/SpineViewer/Views/PreferenceDialog.xaml.cs b/SpineViewer/Views/PreferenceDialog.xaml.cs index 849f47b..27f7aff 100644 --- a/SpineViewer/Views/PreferenceDialog.xaml.cs +++ b/SpineViewer/Views/PreferenceDialog.xaml.cs @@ -1,4 +1,4 @@ -using SpineViewer.Natives; +using SpineViewer.Extensions; using SpineViewer.Resources; using SpineViewer.Services; using SpineViewer.ViewModels.Exporters; @@ -16,6 +16,7 @@ using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; +using Win32Natives; namespace SpineViewer.Views { @@ -32,9 +33,8 @@ namespace SpineViewer.Views 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); + this.SetWindowTextColor(AppResource.Color_PrimaryText); + this.SetWindowCaptionColor(AppResource.Color_Region); } private void ButtonOK_Click(object sender, RoutedEventArgs e) diff --git a/SpineViewer/Views/ProgressDialog.xaml.cs b/SpineViewer/Views/ProgressDialog.xaml.cs index fde5c03..d59f955 100644 --- a/SpineViewer/Views/ProgressDialog.xaml.cs +++ b/SpineViewer/Views/ProgressDialog.xaml.cs @@ -1,4 +1,4 @@ -using SpineViewer.Natives; +using SpineViewer.Extensions; using SpineViewer.Resources; using SpineViewer.ViewModels; using System; @@ -16,6 +16,7 @@ using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; +using Win32Natives; namespace SpineViewer.Views { @@ -33,9 +34,8 @@ namespace SpineViewer.Views 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); + this.SetWindowTextColor(AppResource.Color_PrimaryText); + this.SetWindowCaptionColor(AppResource.Color_Region); } private void ProgressWindow_Loaded(object sender, RoutedEventArgs e) diff --git a/SpineViewerCLI/SpineViewerCLI.cs b/SpineViewerCLI/SpineViewerCLI.cs index 9bcbea3..36c2110 100644 --- a/SpineViewerCLI/SpineViewerCLI.cs +++ b/SpineViewerCLI/SpineViewerCLI.cs @@ -42,7 +42,7 @@ namespace SpineViewerCLI } catch (Exception ex) { - _logger.Trace(ex.ToString()); + _logger.Debug(ex.ToString()); _logger.Fatal("Failed to execute, {0}", ex.Message); return -1; } diff --git a/SpineViewerCLI/SpineViewerCLI.csproj b/SpineViewerCLI/SpineViewerCLI.csproj index 680952a..837c393 100644 --- a/SpineViewerCLI/SpineViewerCLI.csproj +++ b/SpineViewerCLI/SpineViewerCLI.csproj @@ -8,7 +8,7 @@ net8.0 $(SolutionDir)out false - 0.16.11 + 0.16.12 Exe diff --git a/SpineViewer/Natives/Dwmapi.cs b/Win32Natives/Dwmapi.cs similarity index 81% rename from SpineViewer/Natives/Dwmapi.cs rename to Win32Natives/Dwmapi.cs index 29fe400..2776186 100644 --- a/SpineViewer/Natives/Dwmapi.cs +++ b/Win32Natives/Dwmapi.cs @@ -4,9 +4,8 @@ using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; -using System.Windows.Media; -namespace SpineViewer.Natives +namespace Win32Natives { /// /// dwmapi.dll 包装类 @@ -24,15 +23,15 @@ namespace SpineViewer.Natives [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) + public static bool SetWindowCaptionColor(IntPtr hwnd, byte r, byte g, byte b) { - int c = color.R | (color.G << 8) | (color.B << 16); + int c = r | (g << 8) | (b << 16); return 0 == DwmSetWindowAttribute(hwnd, DWMWA_CAPTION_COLOR, ref c, sizeof(uint)); } - public static bool SetWindowTextColor(IntPtr hwnd, Color color) + public static bool SetWindowTextColor(IntPtr hwnd, byte r, byte g, byte b) { - int c = color.R | (color.G << 8) | (color.B << 16); + int c = r | (g << 8) | (b << 16); return 0 == DwmSetWindowAttribute(hwnd, DWMWA_TEXT_COLOR, ref c, sizeof(uint)); } diff --git a/SpineViewer/Natives/Gdi32.cs b/Win32Natives/Gdi32.cs similarity index 96% rename from SpineViewer/Natives/Gdi32.cs rename to Win32Natives/Gdi32.cs index 5845cf9..fb3e77e 100644 --- a/SpineViewer/Natives/Gdi32.cs +++ b/Win32Natives/Gdi32.cs @@ -7,7 +7,7 @@ using System.Text; using System.Threading.Tasks; using System.Windows; -namespace SpineViewer.Natives +namespace Win32Natives { /// /// gdi32.dll 包装类 diff --git a/SpineViewer/Natives/Shell32.cs b/Win32Natives/Shell32.cs similarity index 96% rename from SpineViewer/Natives/Shell32.cs rename to Win32Natives/Shell32.cs index 1a08aa6..e6ac8ba 100644 --- a/SpineViewer/Natives/Shell32.cs +++ b/Win32Natives/Shell32.cs @@ -7,7 +7,7 @@ using System.Text; using System.Threading.Tasks; using System.Windows; -namespace SpineViewer.Natives +namespace Win32Natives { /// /// shell32.dll 包装类 diff --git a/SpineViewer/Natives/User32.cs b/Win32Natives/User32.cs similarity index 99% rename from SpineViewer/Natives/User32.cs rename to Win32Natives/User32.cs index 4702bd6..0d25a62 100644 --- a/SpineViewer/Natives/User32.cs +++ b/Win32Natives/User32.cs @@ -7,7 +7,7 @@ using System.Text; using System.Threading.Tasks; using System.Windows; -namespace SpineViewer.Natives +namespace Win32Natives { /// /// user32.dll 包装类 @@ -316,7 +316,7 @@ namespace SpineViewer.Natives workerw = FindWindowEx(progman, IntPtr.Zero, "WorkerW", null); } - Debug.WriteLine($"HWND(WorkerW): {workerw:x8}"); + Debug.WriteLine($"HWND(WorkerW): 0x{workerw:x8}"); return workerw; } diff --git a/Win32Natives/Win32Natives.csproj b/Win32Natives/Win32Natives.csproj new file mode 100644 index 0000000..1ae1ffe --- /dev/null +++ b/Win32Natives/Win32Natives.csproj @@ -0,0 +1,14 @@ + + + + enable + enable + x64 + x64 + net8.0-windows + $(SolutionDir)out + false + 0.16.0 + + +