添加单实例限制、应用图标、移除托盘设置菜单、快捷键暂停/恢复功能

单实例限制:通过命名Mutex和窗口消息广播确保只能运行一个实例,再次启动时唤起已有窗口

应用图标:exe文件嵌入app.ico,托盘和窗口图标统一使用该图标文件

移除托盘右键菜单中与显示主界面重复的设置选项

快捷键暂停/恢复:托盘菜单和主界面侧边栏均添加切换按钮,通过MainViewModel.IsHotKeyEnabled双向同步
This commit is contained in:
2026-05-10 14:10:52 +08:00
parent b715904439
commit f33c89d2c4
8 changed files with 116 additions and 26 deletions

View File

@@ -3,10 +3,13 @@ using System.Collections.Specialized;
using System.ComponentModel;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Data;
using System.Windows.Forms;
using System.Windows.Interop;
using System.Windows.Media.Imaging;
using FontAwesome.Sharp;
using PersonalToolBox.Helpers;
using PersonalToolBox.ViewModels;
@@ -18,8 +21,14 @@ public partial class MainWindow : Window
private readonly MainViewModel _viewModel;
private readonly HotKeyManager _hotKeyManager;
private NotifyIcon? _notifyIcon;
private ToolStripMenuItem? _hotKeyToggleMenuItem;
private bool _canActuallyClose;
[DllImport("user32.dll")]
private static extern uint RegisterWindowMessage(string lpString);
private readonly int _showMainMsg;
public MainWindow(MainViewModel viewModel, HotKeyManager hotKeyManager)
{
InitializeComponent();
@@ -28,7 +37,18 @@ public partial class MainWindow : Window
_hotKeyManager = hotKeyManager;
DataContext = viewModel;
_showMainMsg = (int)RegisterWindowMessage("PersonalToolBox_ShowMain");
var iconPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources", "app.ico");
if (File.Exists(iconPath))
{
using var stream = File.OpenRead(iconPath);
var decoder = BitmapDecoder.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
this.Icon = decoder.Frames[0];
}
viewModel.Logs.CollectionChanged += OnLogsCollectionChanged;
viewModel.PropertyChanged += OnViewModelPropertyChanged;
CreateTrayIcon();
}
@@ -53,9 +73,14 @@ public partial class MainWindow : Window
/// </summary>
private void CreateTrayIcon()
{
var iconPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources", "app.ico");
var trayIcon = File.Exists(iconPath)
? new System.Drawing.Icon(iconPath)
: System.Drawing.SystemIcons.Application;
_notifyIcon = new NotifyIcon
{
Icon = CreateAppIcon(),
Icon = trayIcon,
Visible = true,
Text = "个人工具箱"
};
@@ -68,26 +93,17 @@ public partial class MainWindow : Window
var menu = new ContextMenuStrip();
menu.Items.Add("显示主界面", null, (_, _) => ShowMainWindow());
menu.Items.Add("设置", null, (_, _) => OpenSettings());
_hotKeyToggleMenuItem = new ToolStripMenuItem(
_viewModel.IsHotKeyEnabled ? "暂停快捷键功能" : "恢复快捷键功能");
_hotKeyToggleMenuItem.Click += (_, _) => _viewModel.ToggleHotKeyCommand.Execute(null);
menu.Items.Add(_hotKeyToggleMenuItem);
menu.Items.Add(new ToolStripSeparator());
menu.Items.Add("彻底退出", null, (_, _) => ExitApplication());
_notifyIcon.ContextMenuStrip = menu;
}
/// <summary>
/// 程序化生成 32x32 托盘图标
/// </summary>
private static System.Drawing.Icon CreateAppIcon()
{
var bmp = new System.Drawing.Bitmap(32, 32);
using var g = System.Drawing.Graphics.FromImage(bmp);
g.Clear(System.Drawing.Color.FromArgb(30, 30, 46));
using var font = new System.Drawing.Font(System.Drawing.FontFamily.GenericSansSerif, 16, System.Drawing.FontStyle.Bold);
using var brush = new System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(137, 180, 250));
g.DrawString("T", font, brush, new System.Drawing.PointF(6, 3));
return System.Drawing.Icon.FromHandle(bmp.GetHicon());
}
/// <summary>
/// 左键托盘图标:切换窗口显示/隐藏
/// </summary>
@@ -109,15 +125,6 @@ public partial class MainWindow : Window
Activate();
}
/// <summary>
/// 打开设置(当前无额外设置界面,提示使用内置功能)
/// </summary>
private void OpenSettings()
{
ShowMainWindow();
_viewModel.LogServiceMessage("设置功能可通过左侧栏管理分类和主题切换");
}
/// <summary>
/// 彻底退出程序
/// </summary>
@@ -146,10 +153,26 @@ public partial class MainWindow : Window
private IntPtr WndProcHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == _showMainMsg)
{
Dispatcher.Invoke(() => ShowMainWindow());
handled = true;
return IntPtr.Zero;
}
handled = _hotKeyManager.TryHandleMessage(msg, wParam, lParam);
return IntPtr.Zero;
}
private void OnViewModelPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(MainViewModel.IsHotKeyEnabled) && _hotKeyToggleMenuItem != null)
{
bool enabled = _viewModel.IsHotKeyEnabled;
_hotKeyToggleMenuItem.Text = enabled ? "暂停快捷键功能" : "恢复快捷键功能";
}
}
private void OnLogsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add && LogListBox.Items.Count > 0)