From 8773774da048558a61a9528d883f6864ffdf630a Mon Sep 17 00:00:00 2001 From: Mikhail Zaytsev Date: Thu, 19 Jun 2025 23:39:27 +0700 Subject: [PATCH] Add indicator on tray icon --- InvisibleMan-XRay/Factories/WindowFactory.cs | 5 ++- InvisibleMan-XRay/Handlers/NotifyHandler.cs | 42 +++++++++++++++++++ .../Windows/MainWindow/MainWindow.xaml.cs | 14 ++++++- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/InvisibleMan-XRay/Factories/WindowFactory.cs b/InvisibleMan-XRay/Factories/WindowFactory.cs index 38d8aa5..8906689 100644 --- a/InvisibleMan-XRay/Factories/WindowFactory.cs +++ b/InvisibleMan-XRay/Factories/WindowFactory.cs @@ -30,6 +30,7 @@ public MainWindow CreateMainWindow() UpdateHandler updateHandler = handlersManager.GetHandler(); BroadcastHandler broadcastHandler = handlersManager.GetHandler(); SettingsHandler settingsHandler = handlersManager.GetHandler(); + NotifyHandler notifyHandler = handlersManager.GetHandler(); LinkHandler linkHandler = handlersManager.GetHandler(); MainWindow mainWindow = new MainWindow(); @@ -37,6 +38,7 @@ public MainWindow CreateMainWindow() isNeedToShowPolicyWindow: IsNeedToShowPolicyWindow, shouldStartHidden: ShouldStartHidden, isNeedToAutoConnect: IsNeedToAutoConnect, + getMode: settingsHandler.UserSettings.GetMode, getConfig: configHandler.GetCurrentConfig, loadConfig: core.LoadConfig, enableMode: core.EnableMode, @@ -54,7 +56,8 @@ public MainWindow CreateMainWindow() onGenerateClientId: settingsHandler.GenerateClientId, onGitHubClick: linkHandler.OpenGitHubRepositoryLink, onBugReportingClick: linkHandler.OpenBugReportingLink, - onCustomLinkClick: linkHandler.OpenCustomLink + onCustomLinkClick: linkHandler.OpenCustomLink, + setIndicator: notifyHandler.SetIndicator ); return mainWindow; diff --git a/InvisibleMan-XRay/Handlers/NotifyHandler.cs b/InvisibleMan-XRay/Handlers/NotifyHandler.cs index 29f5df6..0764e52 100644 --- a/InvisibleMan-XRay/Handlers/NotifyHandler.cs +++ b/InvisibleMan-XRay/Handlers/NotifyHandler.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Drawing; +using System.Drawing.Drawing2D; using System.Windows.Forms; using System.Collections.Generic; @@ -14,6 +15,7 @@ namespace InvisibleManXRay.Handlers public class NotifyHandler : Handler, IDisposable { private NotifyIcon notifyIcon; + private Icon baseIcon; private Func getMode; private Action onOpenClick; @@ -61,6 +63,7 @@ public void InitializeNotifyIcon() notifyIcon = new NotifyIcon(); notifyIcon.Icon = GetNotifyIcon(); + baseIcon = notifyIcon.Icon; notifyIcon.Visible = true; HandleNotifyIconClick(); @@ -183,6 +186,45 @@ private void CheckItem(ToolStripMenuItem item) item.Checked = true; } + public void SetIndicator(Mode? mode) + { + if (notifyIcon == null || baseIcon == null) + return; + + if (mode == null) + { + notifyIcon.Icon = baseIcon; + return; + } + + Color color = mode == Mode.TUN ? Color.Red : Color.Blue; + notifyIcon.Icon = CreateIndicatorIcon(color); + } + private Icon CreateIndicatorIcon(Color color) + { + using (Bitmap bmp = baseIcon.ToBitmap()) + using (Graphics g = Graphics.FromImage(bmp)) + using (Brush brush = new SolidBrush(color)) + using (Pen outline = new Pen(Color.White, 1)) + { + int size = bmp.Width / 3 + 2; + int x = bmp.Width - size - 1; + int y = bmp.Height - size - 1; + + g.SmoothingMode = SmoothingMode.AntiAlias; + g.FillEllipse(brush, x, y, size, size); + g.DrawEllipse(outline, x, y, size, size); + + IntPtr hIcon = bmp.GetHicon(); + Icon icon = (Icon)Icon.FromHandle(hIcon).Clone(); + DestroyIcon(hIcon); + return icon; + + [System.Runtime.InteropServices.DllImport("user32.dll")] + static extern bool DestroyIcon(IntPtr handle); + } + } + public void Dispose() { notifyIcon?.Dispose(); diff --git a/InvisibleMan-XRay/Windows/MainWindow/MainWindow.xaml.cs b/InvisibleMan-XRay/Windows/MainWindow/MainWindow.xaml.cs index bca4d27..f472905 100644 --- a/InvisibleMan-XRay/Windows/MainWindow/MainWindow.xaml.cs +++ b/InvisibleMan-XRay/Windows/MainWindow/MainWindow.xaml.cs @@ -27,6 +27,7 @@ public partial class MainWindow : Window private Func openUpdateWindow; private Func openAboutWindow; private Func openPolicyWindow; + private Func getMode; private Action onRunServer; private Action onCancelServer; private Action onStopServer; @@ -35,6 +36,7 @@ public partial class MainWindow : Window private Action onGitHubClick; private Action onBugReportingClick; private Action onCustomLinkClick; + private Action setIndicator; private BackgroundWorker runWorker; private BackgroundWorker updateWorker; @@ -216,6 +218,7 @@ public void Setup( Func isNeedToShowPolicyWindow, Func shouldStartHidden, Func isNeedToAutoConnect, + Func getMode, Func getConfig, Func loadConfig, Func enableMode, @@ -233,11 +236,13 @@ public void Setup( Action onGenerateClientId, Action onGitHubClick, Action onBugReportingClick, - Action onCustomLinkClick) + Action onCustomLinkClick, + Action setIndicator) { this.isNeedToShowPolicyWindow = isNeedToShowPolicyWindow; this.shouldStartHidden = shouldStartHidden; this.isNeedToAutoConnect = isNeedToAutoConnect; + this.getMode = getMode; this.getConfig = getConfig; this.loadConfig = loadConfig; this.checkForUpdate = checkForUpdate; @@ -256,6 +261,7 @@ public void Setup( this.onGitHubClick = onGitHubClick; this.onBugReportingClick = onBugReportingClick; this.onCustomLinkClick = onCustomLinkClick; + this.setIndicator = setIndicator; UpdateUI(); } @@ -430,6 +436,8 @@ private void ShowRunStatus() statusStop.Visibility = Visibility.Hidden; statusWaitForRun.Visibility = Visibility.Hidden; + setIndicator?.Invoke(getMode?.Invoke()); + buttonStop.Visibility = Visibility.Visible; buttonCancel.Visibility = Visibility.Hidden; buttonRun.Visibility = Visibility.Hidden; @@ -441,6 +449,8 @@ private void ShowStopStatus() statusRun.Visibility = Visibility.Hidden; statusWaitForRun.Visibility = Visibility.Hidden; + setIndicator?.Invoke(null); + buttonRun.Visibility = Visibility.Visible; buttonCancel.Visibility = Visibility.Hidden; buttonStop.Visibility = Visibility.Hidden; @@ -452,6 +462,8 @@ private void ShowWaitForRunStatus() statusStop.Visibility = Visibility.Hidden; statusRun.Visibility = Visibility.Hidden; + setIndicator?.Invoke(null); + buttonCancel.Visibility = Visibility.Visible; buttonRun.Visibility = Visibility.Hidden; buttonStop.Visibility = Visibility.Hidden;