Windows系统托盘应用开发:C#是否有可复用基类或SDK?
C#系统托盘应用复用标准控件实现方案
Windows没有直接提供完全匹配你需求的现成控件类,但可以基于.NET原生组件结合系统API,实现和Windows标准音量控制、日历一致的体验,无需从零实现所有逻辑:
1. 点击托盘图标弹出窗体+关闭隐藏图标面板
用.NET自带的NotifyIcon处理点击事件,配合Windows API关闭隐藏图标面板:
[DllImport("shell32.dll")] private static extern bool Shell_NotifyIconGetRect(ref NOTIFYICONIDENTIFIER identifier, out RECT iconRect); [DllImport("user32.dll")] private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] private static extern bool SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); // 定义所需结构体 [StructLayout(LayoutKind.Sequential)] public struct NOTIFYICONIDENTIFIER { public uint cbSize; public IntPtr hWnd; public uint uID; public Guid guidItem; } [StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left; public int Top; public int Right; public int Bottom; } private void NotifyIcon_Click(object sender, EventArgs e) { // 关闭隐藏图标面板 IntPtr overflowWindow = FindWindow("NotifyIconOverflowWindow", null); if (overflowWindow != IntPtr.Zero) { SendMessage(overflowWindow, 0x0010, IntPtr.Zero, IntPtr.Zero); // WM_CLOSE } // 弹出自定义窗体 var trayForm = new TrayPopupForm(); trayForm.Show(); }
2. 窗体对齐托盘所在屏幕的右下角
先通过API获取托盘图标位置,再定位到对应屏幕的右下角:
private void PositionForm(Form form) { var identifier = new NOTIFYICONIDENTIFIER { cbSize = (uint)Marshal.SizeOf(typeof(NOTIFYICONIDENTIFIER)), hWnd = notifyIcon1.Handle, uID = notifyIcon1.ID }; if (Shell_NotifyIconGetRect(ref identifier, out RECT iconRect)) { Point iconCenter = new Point((iconRect.Left + iconRect.Right) / 2, (iconRect.Top + iconRect.Bottom) / 2); Screen targetScreen = Screen.FromPoint(iconCenter); // 对齐屏幕工作区右下角 form.Location = new Point( targetScreen.WorkingArea.Right - form.Width, targetScreen.WorkingArea.Bottom - form.Height ); } }
调用:在窗体Show()前执行PositionForm(trayForm)。
3. 失去焦点自动关闭窗体
给窗体添加Deactivate事件,加短延迟避免误关闭:
private void TrayPopupForm_Deactivate(object sender, EventArgs e) { Task.Delay(100).ContinueWith(_ => this.Invoke(new Action(() => this.Close()))); }
外观一致性保障
- 设置窗体
FormBorderStyle = FormBorderStyle.None,模拟原生弹出面板样式 - 控件使用
FlatStyle.System,确保跟随系统主题渲染 - 可借助
VisualStyleRenderer自定义绘制控件,完全匹配系统视觉风格
内容的提问来源于stack exchange,提问作者Deling Ren
相关产品推荐
相关产品推荐

