XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

HaloPixelToolBox

【WinUI3】基于USB HID通讯的花再音响工具箱

公开
关注 0 Fork 0 Star 0
返回提交历史

XFEstudio/HaloPixelToolBox

优化托盘界面外观

95505c4
XFE工作室室长 <mail@xfegzs.com>
提交于

代码差异

7 个文件 +232 -144
Modified HaloPixelToolBox/HaloPixelToolBox/App.xaml.cs +75 -76
@@ -8,100 +8,99 @@ using XFEExtension.NetCore.WinUIHelper.Utilities;
8 8 using XFEExtension.NetCore.WinUIHelper.Utilities.Helper;
9 9 using XFEExtension.NetCore.XFEConsole;
10 10
11 namespace HaloPixelToolBox
11 namespace HaloPixelToolBox;
12
13 /// <summary>
14 /// Provides application-specific behavior to supplement the default Application class.
15 /// </summary>
16 public partial class App : Application
12 17 {
18 public ITrayIconService TrayIconService { get; } = ServiceManager.GetService<ITrayIconService>();
19 /// <summary>
20 /// 主页窗口
21 /// </summary>
22 public static MainWindow MainWindow { get; set; } = new();
23
13 24 /// <summary>
14 /// Provides application-specific behavior to supplement the default Application class.
25 /// Initializes the singleton application object. This is the first line of authored code
26 /// executed, and as such is the logical equivalent of main() or WinMain().
15 27 /// </summary>
16 public partial class App : Application
28 public App()
17 29 {
18 public ITrayIconService TrayIconService { get; } = ServiceManager.GetService<ITrayIconService>();
19 /// <summary>
20 /// 主页窗口
21 /// </summary>
22 public static MainWindow MainWindow { get; set; } = new();
30 XFEConsole.UseXFEConsoleLog();
31 XFEConsole.Log.LogPath = Path.Combine(AppPath.LogDictionary, XFEConsole.Log.LogPath);
32 Console.WriteLine("正在初始化应用程序...");
33 this.InitializeComponent();
34 Console.WriteLine("应用程序初始化完成");
35 AppThemeHelper.Theme = SystemProfile.Theme;
36 PageManager.RegisterPage(typeof(AppShellPage));
37 PageManager.RegisterPage(typeof(CloudMusicLyricsToolPage));
38 PageManager.RegisterPage(typeof(MainPage));
39 PageManager.RegisterPage(typeof(SettingPage));
40 UnhandledException += App_UnhandledException;
41 AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
42 AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
43 }
23 44
24 /// <summary>
25 /// Initializes the singleton application object. This is the first line of authored code
26 /// executed, and as such is the logical equivalent of main() or WinMain().
27 /// </summary>
28 public App()
45 private void CurrentDomain_UnhandledException(object sender, System.UnhandledExceptionEventArgs e)
46 {
47 if (e.ExceptionObject is Exception ex)
29 48 {
30 XFEConsole.UseXFEConsoleLog();
31 XFEConsole.Log.LogPath = Path.Combine(AppPath.LogDictionary, XFEConsole.Log.LogPath);
32 Console.WriteLine("正在初始化应用程序...");
33 this.InitializeComponent();
34 Console.WriteLine("应用程序初始化完成");
35 AppThemeHelper.Theme = SystemProfile.Theme;
36 PageManager.RegisterPage(typeof(AppShellPage));
37 PageManager.RegisterPage(typeof(CloudMusicLyricsToolPage));
38 PageManager.RegisterPage(typeof(MainPage));
39 PageManager.RegisterPage(typeof(SettingPage));
40 UnhandledException += App_UnhandledException;
41 AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
42 AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
49 Console.WriteLine($"[ERROR]{ex.Message}");
50 Console.WriteLine($"[TRACE]{ex.StackTrace}");
43 51 }
44
45 private void CurrentDomain_UnhandledException(object sender, System.UnhandledExceptionEventArgs e)
52 else
46 53 {
47 if (e.ExceptionObject is Exception ex)
48 {
49 Console.WriteLine($"[ERROR]{ex.Message}");
50 Console.WriteLine($"[TRACE]{ex.StackTrace}");
51 }
52 else
53 {
54 Console.WriteLine("[ERROR]发生未处理的异常,但无法获取异常信息");
55 Console.WriteLine(e.ExceptionObject.ToString());
56 }
54 Console.WriteLine("[ERROR]发生未处理的异常,但无法获取异常信息");
55 Console.WriteLine(e.ExceptionObject.ToString());
57 56 }
57 }
58 58
59 private void CurrentDomain_ProcessExit(object? sender, EventArgs e)
59 private void CurrentDomain_ProcessExit(object? sender, EventArgs e)
60 {
61 Console.WriteLine("正在退出...");
62 Console.WriteLine("正在保存日志...");
63 var logs = Directory.GetFiles(AppPath.LogDictionary);
64 if (logs.Length > 10)
60 65 {
61 Console.WriteLine("正在退出...");
62 Console.WriteLine("正在保存日志...");
63 var logs = Directory.GetFiles(AppPath.LogDictionary);
64 if (logs.Length > 10)
66 foreach (var log in logs.OrderByDescending(x => x).Skip(10))
65 67 {
66 foreach (var log in logs.OrderByDescending(x => x).Skip(10))
67 {
68 File.Delete(log);
69 }
68 File.Delete(log);
70 69 }
71 Console.WriteLine("日志保存成功");
72 70 }
71 Console.WriteLine("日志保存成功");
72 }
73 73
74 private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e)
74 private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e)
75 {
76 if (ServiceManager.GetService<IMessageService>() is IMessageService messageService)
75 77 {
76 if (ServiceManager.GetService<IMessageService>() is IMessageService messageService)
77 {
78 messageService.ShowMessage(e.Message, "发生错误", InfoBarSeverity.Error);
79 Console.WriteLine($"[ERROR]{e.Message}");
80 Console.WriteLine($"[TRACE]{e.Exception.StackTrace}");
81 e.Handled = true;
82 }
78 messageService.ShowMessage(e.Message, "发生错误", InfoBarSeverity.Error);
79 Console.WriteLine($"[ERROR]{e.Message}");
80 Console.WriteLine($"[TRACE]{e.Exception.StackTrace}");
81 e.Handled = true;
83 82 }
83 }
84 84
85 /// <summary>
86 /// Invoked when the application is launched.
87 /// </summary>
88 /// <param name="args">Details about the launch request and process.</param>
89 protected override void OnLaunched(LaunchActivatedEventArgs args)
90 {
91 TrayIconService.Initilize(DispatcherQueue.GetForCurrentThread());
92 MainWindow.Closed += MainWindow_Closed;
93 MainWindow.Content = new AppShellPage();
94 if (SystemProfile.MinimizeWhenOpen)
95 MainWindow.AppWindow.Hide();
96 else
97 MainWindow.Activate();
98 AppThemeHelper.MainWindow = MainWindow;
99 }
85 /// <summary>
86 /// Invoked when the application is launched.
87 /// </summary>
88 /// <param name="args">Details about the launch request and process.</param>
89 protected override void OnLaunched(LaunchActivatedEventArgs args)
90 {
91 TrayIconService.Initilize(DispatcherQueue.GetForCurrentThread());
92 MainWindow.Closed += MainWindow_Closed;
93 MainWindow.Content = new AppShellPage();
94 if (SystemProfile.MinimizeWhenOpen)
95 MainWindow.AppWindow.Hide();
96 else
97 MainWindow.Activate();
98 AppThemeHelper.MainWindow = MainWindow;
99 }
100 100
101 private void MainWindow_Closed(object sender, WindowEventArgs args)
102 {
103 Win32Helper.ShowWindow(WindowHelper.GetHwndForCurrentWindow(), Win32Helper.SW_HIDE);
104 args.Handled = true;
105 }
101 private void MainWindow_Closed(object sender, WindowEventArgs args)
102 {
103 Win32Helper.ShowWindow(WindowHelper.GetHwndForCurrentWindow(), Win32Helper.SW_HIDE);
104 args.Handled = true;
106 105 }
107 106 }
Modified HaloPixelToolBox/HaloPixelToolBox/Implements/Services/TrayIconService.cs +1 -0
@@ -56,6 +56,7 @@ public partial class TrayIconService : GlobalServiceBase, ITrayIconService
56 56 var menu = new TrayMenuWindow();
57 57 menu.AppWindow.MoveInZOrderAtTop();
58 58 menu.AppWindow.SetPresenter(AppWindowPresenterKind.Overlapped);
59 menu.AppWindow.IsShownInSwitchers = false;
59 60 if (menu.AppWindow.Presenter is OverlappedPresenter presenter)
60 61 {
61 62 presenter.SetBorderAndTitleBar(true, false);
Modified HaloPixelToolBox/HaloPixelToolBox/TrayMenuWindow.xaml +1 -1
@@ -11,6 +11,6 @@
11 11 Title="TrayMenuWindow">
12 12
13 13 <Window.SystemBackdrop>
14 <MicaBackdrop />
14 <DesktopAcrylicBackdrop/>
15 15 </Window.SystemBackdrop>
16 16 </Window>
Modified HaloPixelToolBox/HaloPixelToolBox/TrayMenuWindow.xaml.cs +2 -0
@@ -1,3 +1,5 @@
1 using Microsoft.UI.Xaml.Media;
2
1 3 namespace HaloPixelToolBox;
2 4
3 5 /// <summary>
Added HaloPixelToolBox/HaloPixelToolBox/ViewModels/TrayMenuPageViewModel.cs +103 -0
@@ -0,0 +1,103 @@
1 using CommunityToolkit.Mvvm.Input;
2 using HaloPixelToolBox.Interface.Services;
3 using HaloPixelToolBox.Utilities.Helpers;
4 using HaloPixelToolBox.Utilities.Helpers.Win32;
5 using HaloPixelToolBox.Views;
6 using Microsoft.UI.Dispatching;
7 using System.Runtime.InteropServices;
8 using XFEExtension.NetCore.WinUIHelper.Implements;
9 using XFEExtension.NetCore.WinUIHelper.Utilities;
10
11 namespace HaloPixelToolBox.ViewModels;
12
13 public partial class TrayMenuPageViewModel : ServiceBaseViewModelBase<string>
14 {
15 IntPtr _mouseHook = new();
16 LowLevelMouseProc? _proc;
17 public Window MenuWindow { get; set; }
18 public DispatcherQueue DispatcherQueue => MenuWindow.DispatcherQueue;
19
20 public TrayMenuPageViewModel(Window window)
21 {
22 MenuWindow = window;
23 AutoNavigationParameterService.ParameterChange += AutoNavigationParameterService_ParameterChange;
24 }
25
26 private void AutoNavigationParameterService_ParameterChange(object? sender, string? e)
27 {
28 if (AutoNavigationParameterService.CurrentPage is not null)
29 {
30 AutoNavigationParameterService.CurrentPage.Unloaded += CurrentPage_Unloaded;
31 }
32 InstallMouseHook();
33 }
34
35 private void CurrentPage_Unloaded(object sender, RoutedEventArgs e)
36 {
37 UnInstallMouseHook();
38 }
39
40 void UnInstallMouseHook()
41 {
42 if (_mouseHook != IntPtr.Zero)
43 {
44 Win32Helper.UnhookWindowsHookEx(_mouseHook);
45 _mouseHook = IntPtr.Zero;
46 }
47 }
48
49 void InstallMouseHook()
50 {
51 _proc = HookCallback;
52 _mouseHook = Win32Helper.SetWindowsHookEx(Win32Helper.WH_MOUSE_LL, _proc, IntPtr.Zero, 0);
53 }
54
55 IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
56 {
57 try
58 {
59 if (nCode >= 0 && wParam == Win32Helper.WM_LBUTTONDOWN)
60 {
61 var hook = Marshal.PtrToStructure<MSLLHOOKSTRUCT>(lParam);
62 var pt = hook.pt;
63
64 var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(MenuWindow);
65 Win32Helper.GetWindowRect(hwnd, out RECT rect);
66
67 bool inside =
68 pt.x >= rect.Left && pt.x <= rect.Right &&
69 pt.y >= rect.Top && pt.y <= rect.Bottom;
70
71 if (!inside)
72 {
73 DispatcherQueue.TryEnqueue(() =>
74 {
75 MenuWindow.Close();
76 });
77 }
78 }
79 }
80 catch { }
81
82 return Win32Helper.CallNextHookEx(_mouseHook, nCode, wParam, lParam);
83 }
84
85 [RelayCommand]
86 void Show()
87 {
88 ServiceManager.GetGlobalService<ITrayIconService>()?.ShowWindow();
89 NavigationViewService?.NavigateTo<CloudMusicLyricsToolPage>();
90 MenuWindow.Close();
91 }
92
93 [RelayCommand]
94 void OpenSettings()
95 {
96 ServiceManager.GetGlobalService<ITrayIconService>()?.ShowWindow();
97 NavigationViewService?.NavigateTo<SettingPage>();
98 MenuWindow.Close();
99 }
100
101 [RelayCommand]
102 static void Exit() => ServiceManager.GetGlobalService<ITrayIconService>()?.ExitApp();
103 }
Modified HaloPixelToolBox/HaloPixelToolBox/Views/TrayMenuPage.xaml +41 -7
@@ -6,16 +6,50 @@
6 6 xmlns:local="using:HaloPixelToolBox.Views"
7 7 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
8 8 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
9 mc:Ignorable="d">
9 mc:Ignorable="d" Loaded="Page_Loaded" Background="{ThemeResource DesktopAcrylicTransparentBrush}">
10 <Page.Resources>
11 <Style x:Key="MenuButtonStyle" TargetType="Button">
12 <Style.Setters>
13 <Setter Property="Background" Value="Transparent"/>
14 <Setter Property="CornerRadius" Value="0"/>
15 <Setter Property="BorderThickness" Value="0"/>
16 <Setter Property="HorizontalAlignment" Value="Stretch"/>
17 <Setter Property="HorizontalContentAlignment" Value="Left"/>
18 </Style.Setters>
19 </Style>
20 <Style x:Key="MenuSeparatorStyle" TargetType="MenuFlyoutSeparator">
21 <Style.Setters>
22 <Setter Property="Margin" Value="10,5"/>
23 </Style.Setters>
24 </Style>
25 </Page.Resources>
10 26
11 27 <StackPanel x:Name="panel" HorizontalAlignment="Center" VerticalAlignment="Center">
12 <StackPanel Orientation="Horizontal" Spacing="10" HorizontalAlignment="Center" Padding="20">
28 <StackPanel Orientation="Horizontal" Spacing="10" HorizontalAlignment="Center" Padding="20,20,20,5">
13 29 <Image Source="/Assets/icon.png" HorizontalAlignment="Left" Width="16" Height="16"/>
14 <TextBlock Text="花再音响工具箱" VerticalAlignment="Center"/>
30 <TextBlock Text="花再工具箱" VerticalAlignment="Center"/>
15 31 </StackPanel>
16 <MenuFlyoutSeparator Margin="10,0"/>
17 <Button Content="打开主界面" Click="Show_Click" HorizontalAlignment="Stretch" Style="{StaticResource SubtleButtonStyle}"/>
18 <MenuFlyoutSeparator Margin="10,0"/>
19 <Button Content="退出" Click="Exit_Click" HorizontalAlignment="Stretch" Style="{StaticResource SubtleButtonStyle}"/>
32 <MenuFlyoutSeparator Style="{ThemeResource MenuSeparatorStyle}"/>
33 <Button Command="{x:Bind ViewModel.ShowCommand}" Style="{ThemeResource MenuButtonStyle}">
34 <StackPanel Orientation="Horizontal" Spacing="10" HorizontalAlignment="Left">
35 <FontIcon Glyph="&#xE80F;" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="15"/>
36 <TextBlock Grid.Column="1" Text="主页" VerticalAlignment="Center"/>
37 </StackPanel>
38 </Button>
39 <MenuFlyoutSeparator Style="{ThemeResource MenuSeparatorStyle}"/>
40 <Button Command="{x:Bind ViewModel.OpenSettingsCommand}" Style="{ThemeResource MenuButtonStyle}">
41 <StackPanel Orientation="Horizontal" Spacing="10" HorizontalAlignment="Left">
42 <FontIcon Glyph="&#xE713;" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="15"/>
43 <TextBlock Grid.Column="1" Text="设置" VerticalAlignment="Center"/>
44 </StackPanel>
45 </Button>
46 <MenuFlyoutSeparator Style="{ThemeResource MenuSeparatorStyle}"/>
47 <Button Command="{x:Bind ViewModel.ExitCommand}" Style="{ThemeResource MenuButtonStyle}">
48 <StackPanel Orientation="Horizontal" Spacing="10" HorizontalAlignment="Left">
49 <FontIcon Glyph="&#xE89F;" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="15"/>
50 <TextBlock Text="退出" VerticalAlignment="Center"/>
51 </StackPanel>
52 </Button>
53 <Grid Margin="0,5"/>
20 54 </StackPanel>
21 55 </Page>
Modified HaloPixelToolBox/HaloPixelToolBox/Views/TrayMenuPage.xaml.cs +9 -60
@@ -1,34 +1,24 @@
1 using HaloPixelToolBox.Interface.Services;
2 using HaloPixelToolBox.Utilities.Helpers;
3 using HaloPixelToolBox.Utilities.Helpers.Win32;
4 using System.Runtime.InteropServices;
5 1 using System.Windows.Forms;
6 2 using Windows.Graphics;
7 using XFEExtension.NetCore.WinUIHelper.Utilities;
8 3
9 4 namespace HaloPixelToolBox.Views;
10 5
11 6 /// <summary>
12 /// An empty page that can be used on its own or navigated to within a Frame.
7 /// ���̲˵�ҳ��
13 8 /// </summary>
14 9 public sealed partial class TrayMenuPage : Page
15 10 {
16 IntPtr _mouseHook = new();
17 LowLevelMouseProc? _proc;
18 11 public Window MenuWindow { get; set; }
12 public TrayMenuPageViewModel ViewModel { get; set; }
13 public static TrayMenuPage? Current { get; set; }
19 14
20 15 public TrayMenuPage(Window window)
21 16 {
17 Current = this;
22 18 MenuWindow = window;
19 ViewModel = new(window);
23 20 InitializeComponent();
24 this.Loaded += (_, __) =>
25 {
26 DispatcherQueue.TryEnqueue(() =>
27 {
28 ResizeToContent();
29 });
30 };
31 InstallMouseHook();
21 ViewModel.AutoNavigationParameterService.Initialize(this);
32 22 }
33 23
34 24 void ResizeToContent()
@@ -48,50 +38,9 @@ public sealed partial class TrayMenuPage : Page
48 38 MenuWindow.AppWindow.Move(new PointInt32(Cursor.Position.X + 5, Cursor.Position.Y - h + 10));
49 39 }
50 40
51 private void Show_Click(object _, RoutedEventArgs __)
41 private void Page_Loaded(object sender, RoutedEventArgs e)
52 42 {
53 ServiceManager.GetGlobalService<ITrayIconService>()?.ShowWindow();
54 MenuWindow.Close();
55 }
56
57 private void Exit_Click(object _, RoutedEventArgs __)
58 {
59 ServiceManager.GetGlobalService<ITrayIconService>()?.ExitApp();
60 }
61
62 void InstallMouseHook()
63 {
64 _proc = HookCallback;
65 _mouseHook = Win32Helper.SetWindowsHookEx(Win32Helper.WH_MOUSE_LL, _proc, IntPtr.Zero, 0);
66 }
67
68 IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
69 {
70 try
71 {
72 if (nCode >= 0 && wParam == Win32Helper.WM_LBUTTONDOWN)
73 {
74 var hook = Marshal.PtrToStructure<MSLLHOOKSTRUCT>(lParam);
75 var pt = hook.pt;
76
77 var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(MenuWindow);
78 Win32Helper.GetWindowRect(hwnd, out RECT rect);
79
80 bool inside =
81 pt.x >= rect.Left && pt.x <= rect.Right &&
82 pt.y >= rect.Top && pt.y <= rect.Bottom;
83
84 if (!inside)
85 {
86 DispatcherQueue.TryEnqueue(() =>
87 {
88 MenuWindow.Close();
89 });
90 }
91 }
92 }
93 catch { }
94
95 return Win32Helper.CallNextHookEx(_mouseHook, nCode, wParam, lParam);
43 DispatcherQueue.TryEnqueue(ResizeToContent);
44 ViewModel.AutoNavigationParameterService.OnParameterChange(string.Empty);
96 45 }
97 46 }