WPF系统托盘NotifyIcon如何适配深色/浅色模式修改右键菜单背景
NotifyIcon 深浅模式适配方案
你当前使用的是System.Windows.Forms.NotifyIcon控件,它的默认右键菜单属于WinForms原生控件,不会自动适配WPF的主题体系,可通过以下两种方案实现深浅模式适配:
方案1:自定义WinForms菜单绘制(无需额外引入组件)
手动开启上下文菜单的自绘模式,根据当前深浅模式配置绘制样式:
- 初始化时为NotifyIcon绑定支持自绘的上下文菜单
_notifyIcon = new Forms.NotifyIcon(); _notifyIcon.Icon = MySystray.Resources.Systray_icon; _notifyIcon.Text = APP_NAME; // 新增上下文菜单配置 var contextMenu = new Forms.ContextMenu(); contextMenu.OwnerDraw = true; // 开启自定义绘制 contextMenu.MeasureItem += ContextMenu_MeasureItem; contextMenu.DrawItem += ContextMenu_DrawItem; // 按需添加菜单项示例 contextMenu.MenuItems.Add("打开主窗口", (s,e)=>{ /* 业务逻辑 */ }); contextMenu.MenuItems.Add("退出", (s,e)=>{ /* 业务逻辑 */ }); _notifyIcon.ContextMenu = contextMenu;
- 实现测量和绘制事件,适配深浅模式
// 自行维护当前深浅模式状态,可通过Win32 API获取系统主题或跟随应用自身设置 private bool _isDarkMode; private void ContextMenu_MeasureItem(object sender, Forms.MeasureItemEventArgs e) { // 自定义菜单项尺寸 e.ItemHeight = 24; e.ItemWidth = 160; } private void ContextMenu_DrawItem(object sender, Forms.DrawItemEventArgs e) { // 按深浅模式配置颜色 var bgColor = _isDarkMode ? Color.FromArgb(38, 38, 38) : Color.White; var textColor = _isDarkMode ? Color.White : Color.Black; var hoverBgColor = _isDarkMode ? Color.FromArgb(55, 55, 55) : Color.FromArgb(204, 232, 255); // 绘制背景 var useBg = (e.State & Forms.DrawItemState.Selected) != 0 ? hoverBgColor : bgColor; e.Graphics.FillRectangle(new SolidBrush(useBg), e.Bounds); // 绘制文字 var currentItem = ((Forms.ContextMenu)sender).MenuItems[e.Index]; e.Graphics.DrawString(currentItem.Text, e.Font, new SolidBrush(textColor), e.Bounds.Left + 24, e.Bounds.Top + 2); }
- 监听系统主题变化或应用主题切换事件,更新
_isDarkMode值后重建/刷新上下文菜单即可。
方案2:弹出WPF原生ContextMenu(适配成本更低,样式更统一)
放弃WinForms原生菜单,右键点击时直接弹出已经做好深浅模式适配的WPF上下文菜单,可完全复用WPF的样式体系:
_notifyIcon.MouseClick += (s, e) => { if (e.Button != Forms.MouseButtons.Right) return; // 直接使用你WPF项目中已经适配好深浅模式的ContextMenu,可直接从资源字典加载 var wpfMenu = new System.Windows.Controls.ContextMenu(); wpfMenu.Items.Add(new System.Windows.Controls.MenuItem { Header = "打开主窗口" }); wpfMenu.Items.Add(new System.Windows.Controls.MenuItem { Header = "退出" }); // 定位到鼠标位置弹出 wpfMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.MousePoint; wpfMenu.IsOpen = true; };
提示:此方案无需处理WinForms控件的绘制逻辑,只需要保证WPF的ContextMenu已经和应用其他控件共用一套深浅模式样式即可,整体样式一致性更高。
内容的提问来源于stack exchange,提问作者Rajib_119
相关产品推荐
相关产品推荐

