添加单实例限制、应用图标、移除托盘设置菜单、快捷键暂停/恢复功能
单实例限制:通过命名Mutex和窗口消息广播确保只能运行一个实例,再次启动时唤起已有窗口 应用图标:exe文件嵌入app.ico,托盘和窗口图标统一使用该图标文件 移除托盘右键菜单中与显示主界面重复的设置选项 快捷键暂停/恢复:托盘菜单和主界面侧边栏均添加切换按钮,通过MainViewModel.IsHotKeyEnabled双向同步
This commit is contained in:
@@ -178,6 +178,7 @@
|
||||
<RowDefinition Height="42"/>
|
||||
<RowDefinition Height="42"/>
|
||||
<RowDefinition Height="45"/>
|
||||
<RowDefinition Height="45"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<ListBox Grid.Row="0"
|
||||
@@ -277,7 +278,7 @@
|
||||
BorderBrush="{DynamicResource Theme.CardBorder}"
|
||||
Foreground="{DynamicResource Theme.Foreground}"
|
||||
FontSize="12"
|
||||
Height="35" Margin="10,0,10,10"
|
||||
Height="35" Margin="10,0,10,3"
|
||||
Cursor="Hand">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="◐" FontSize="16" Margin="0,0,8,0"
|
||||
@@ -285,6 +286,28 @@
|
||||
<TextBlock Text="切换主题" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
<Button Grid.Row="4"
|
||||
Command="{Binding ToggleHotKeyCommand}"
|
||||
Background="Transparent"
|
||||
BorderThickness="1"
|
||||
BorderBrush="{DynamicResource Theme.CardBorder}"
|
||||
Foreground="{DynamicResource Theme.Foreground}"
|
||||
FontSize="12"
|
||||
Height="35" Margin="10,0,10,10"
|
||||
Cursor="Hand">
|
||||
<Button.Resources>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Text" Value="⏸ 暂停快捷键"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsHotKeyEnabled}" Value="False">
|
||||
<Setter Property="Text" Value="▶ 恢复快捷键"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Button.Resources>
|
||||
<TextBlock VerticalAlignment="Center" TextAlignment="Center"/>
|
||||
</Button>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user