diff --git a/chatclient/App.xaml b/chatclient/App.xaml index 234aed7..43f4d3c 100644 --- a/chatclient/App.xaml +++ b/chatclient/App.xaml @@ -5,14 +5,15 @@ xmlns:local="clr-namespace:chatclient" StartupUri="MainWindow.xaml"> - - - - - - + + + + + + + - - + + diff --git a/chatclient/Data/MaterialTrayMenuItem.xaml b/chatclient/Data/MaterialTrayMenuItem.xaml new file mode 100644 index 0000000..5387ae3 --- /dev/null +++ b/chatclient/Data/MaterialTrayMenuItem.xaml @@ -0,0 +1,45 @@ + + + + + \ No newline at end of file diff --git a/chatclient/Data/TrayIconManager.cs b/chatclient/Data/TrayIconManager.cs new file mode 100644 index 0000000..b4207c7 --- /dev/null +++ b/chatclient/Data/TrayIconManager.cs @@ -0,0 +1,122 @@ +using System.Windows; +using Hardcodet.Wpf.TaskbarNotification; +using System.Windows.Controls; +using MaterialDesignThemes.Wpf; +using System.Windows.Input; +using System.Drawing; +using System.Diagnostics; + +namespace chatclient.Data +{ + public class TrayIconManager + { + private readonly TaskbarIcon _trayIcon; + private readonly Window _mainWindow; + + public TrayIconManager(Window mainWindow) + { + _mainWindow = mainWindow; + + // 创建托盘图标 + _trayIcon = new TaskbarIcon + { + Icon = new System.Drawing.Icon("resource/chat.ico"), + ToolTipText = "Material Design Application", + ContextMenu = CreateContextMenu() + }; + + // 注册事件 + _trayIcon.TrayMouseDoubleClick += TrayIcon_TrayMouseDoubleClick; + _mainWindow.Closing += MainWindow_ClosingHandler; + } + + private void MainWindow_ClosingHandler(object? sender, System.ComponentModel.CancelEventArgs e) + { + // 取消关闭操作,改为最小化到托盘 + e.Cancel = true; + _mainWindow.Hide(); + + // 显示通知 + //_trayIcon.ShowBalloonTip("Application minimized", + // "The application is running in the system tray", + // BalloonIcon.Info); + } + + private ContextMenu CreateContextMenu() + { + // 创建Material Design风格的上下文菜单 + var contextMenu = new ContextMenu + { + Style = (Style)Application.Current.Resources["MaterialTrayMenu"] + }; + + // 添加菜单项 + contextMenu.Items.Add(CreateMenuItem("Open Application", PackIconKind.WindowRestore, OpenApp_Click)); + contextMenu.Items.Add(CreateMenuItem("Settings", PackIconKind.Cog, Settings_Click)); + contextMenu.Items.Add(new Separator { Style = (Style)Application.Current.Resources["MaterialDesignLightSeparator"] }); + contextMenu.Items.Add(CreateMenuItem("Check for Updates", PackIconKind.Update, Updates_Click)); + contextMenu.Items.Add(CreateMenuItem("Help", PackIconKind.HelpCircle, Help_Click)); + contextMenu.Items.Add(new Separator { Style = (Style)Application.Current.Resources["MaterialDesignLightSeparator"] }); + contextMenu.Items.Add(CreateMenuItem("Exit", PackIconKind.Power, Exit_Click)); + + return contextMenu; + } + + private MenuItem CreateMenuItem(string header, PackIconKind iconKind, RoutedEventHandler clickHandler) + { + var menuItem = new MenuItem + { + Header = header, + Style = (Style)Application.Current.Resources["MaterialTrayMenuItem"], + Icon = new PackIcon { Kind = iconKind, Width = 20, Height = 20 } + }; + + menuItem.Click += clickHandler; + return menuItem; + } + + private void TrayIcon_TrayMouseDoubleClick(object sender, RoutedEventArgs e) + { + RestoreApplication(); + } + + private void OpenApp_Click(object sender, RoutedEventArgs e) + { + RestoreApplication(); + } + + private void RestoreApplication() + { + _mainWindow.Show(); + _mainWindow.WindowState = WindowState.Normal; + _mainWindow.Activate(); + } + + private void Settings_Click(object sender, RoutedEventArgs e) + { + // 实现设置逻辑 + } + + private void Updates_Click(object sender, RoutedEventArgs e) + { + // 实现更新检查逻辑 + } + + private void Help_Click(object sender, RoutedEventArgs e) + { + // 实现帮助逻辑 + } + + private void Exit_Click(object sender, RoutedEventArgs e) + { + // 释放托盘图标资源 + Dispose(); + Application.Current.Shutdown(); + } + + public void Dispose() + { + _trayIcon.Dispose(); + } + } +} diff --git a/chatclient/MainWindow.xaml b/chatclient/MainWindow.xaml index 094aebb..af3ebf5 100644 --- a/chatclient/MainWindow.xaml +++ b/chatclient/MainWindow.xaml @@ -8,7 +8,7 @@ xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls" x:Class="chatclient.MainWindow" mc:Ignorable="d" Title="ChatWindow" Height="450" Width="800" MinHeight="240" MinWidth="380" - Style="{StaticResource MaterialDesignWindow}"> + Style="{StaticResource MaterialDesignWindow}" Closed="MainWindow_Closed" Loaded="MainWindow_Loaded"> diff --git a/chatclient/MainWindow.xaml.cs b/chatclient/MainWindow.xaml.cs index 1bf6c2e..6b2c2c2 100644 --- a/chatclient/MainWindow.xaml.cs +++ b/chatclient/MainWindow.xaml.cs @@ -56,6 +56,7 @@ namespace chatclient { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(UpdateName)); } + private TrayIconManager? _trayManager; public MainWindow() { InitializeComponent(); @@ -84,6 +85,8 @@ namespace chatclient MessageScroller.ScrollToEnd(); }), DispatcherPriority.ContextIdle); }; + //Loaded += MainWindow_Loaded; + //Closed += MainWindow_Closed; } public static void StartReceive() { @@ -325,5 +328,18 @@ namespace chatclient Task.Factory.StartNew(() => messageQueue.Enqueue(message)); } } + private void MainWindow_Loaded(object sender, RoutedEventArgs e) + { + // 初始化托盘管理器 + _trayManager = new TrayIconManager(this); + } + private void MainWindow_Closed(object sender, System.EventArgs e) + { + // 清理资源 + Client?.Shutdown(SocketShutdown.Both); + Client?.Close(); + Client?.Dispose(); + _trayManager?.Dispose(); + } } } \ No newline at end of file diff --git a/chatclient/chatclient.csproj b/chatclient/chatclient.csproj index 7f1c629..ed9a950 100644 --- a/chatclient/chatclient.csproj +++ b/chatclient/chatclient.csproj @@ -18,7 +18,9 @@ - + + PreserveNewest +