一键导入
wpf-tray-window-launch
Pattern for launching WPF windows from system tray icon interactions
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Pattern for launching WPF windows from system tray icon interactions
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | wpf-tray-window-launch |
| description | Pattern for launching WPF windows from system tray icon interactions |
| domain | desktop-ui |
| confidence | high |
| source | observed |
When building WPF applications with system tray integration, you need a consistent pattern for launching/showing windows in response to tray icon events (double-click, context menu items).
ElBruno.OllamaMonitor uses H.NotifyIcon.Wpf for tray integration (via NuGet package, wraps System.Windows.Forms.NotifyIcon).
TrayIconService holds direct references to window instances (not factories):
private readonly MainWindow _mainWindow;
private readonly MiniMonitorWindow _miniMonitorWindow;
Windows are constructed once in App.xaml.cs and passed to TrayIconService constructor.
Standard method for showing a window from tray (used by both windows):
private void ShowMiniMonitorWindow()
{
if (!_miniMonitorWindow.IsVisible)
{
_miniMonitorWindow.Show();
}
_miniMonitorWindow.Activate();
}
Key steps:
IsVisible firstShow() if hiddenActivate() to bring to front (handles minimized case implicitly)MainWindow variation includes explicit minimized state check:
if (_mainWindow.WindowState == System.Windows.WindowState.Minimized)
{
_mainWindow.WindowState = System.Windows.WindowState.Normal;
}
Windows implement PrepareForExit() + OnClosing override to hide instead of close:
private bool _allowClose;
public void PrepareForExit() => _allowClose = true;
protected override void OnClosing(CancelEventArgs e)
{
if (!_allowClose)
{
e.Cancel = true;
Hide();
return;
}
base.OnClosing(e);
}
This allows reopening windows without re-instantiation.
Wire tray icon events in TrayIconService constructor:
_notifyIcon.DoubleClick += (_, _) => ShowMiniMonitorWindow();
_notifyIcon.ContextMenuStrip.Opening += (_, _) => RefreshMenuText();
Context menu items use lambda handlers:
new ToolStripMenuItem("Show Mini Monitor", null, (_, _) => ToggleMiniWindowVisibility())
Menu items toggle window visibility with dynamic text:
private void ToggleMiniWindowVisibility()
{
if (_miniMonitorWindow.IsVisible)
{
_miniMonitorWindow.Hide();
return;
}
ShowMiniMonitorWindow();
}
private void RefreshMenuText()
{
_toggleMiniWindowMenuItem.Text = _miniMonitorWindow.IsVisible
? "Hide Mini Monitor"
: "Show Mini Monitor";
}
File: src/ElBruno.OllamaMonitor/Services/TrayIconService.cs
ShowWindow() implementation (MainWindow)ShowMiniMonitorWindow() implementationFile: src/ElBruno.OllamaMonitor/MiniMonitorWindow.xaml.cs
PrepareForExit() + OnClosing() overrideShow() — always call Activate() to handle already-visible-but-background windowsPrepareForExit() — without it, closing a window during app exit triggers unwanted hide logic