添加托盘图标和上下文菜单






4.76/5 (54投票s)
2002年4月11日
3分钟阅读

656711

1
关于添加托盘图标和设置上下文菜单的初学者教程
引言
随着 MFC/SDK 程序员迁移到 .NET,最让他们惊讶的是一切都比以往任何时候都更容易了。 Christian Graus 抱怨说这太容易了,并且对goto的糟糕使用感到恼火。 他可能说的有道理,但让编码变得容易毕竟不是一件坏事。 想到 Chris Maunder 和其他人为那些 MFC 和 SDK 托盘图标类所做的努力,这些类在复制/粘贴程序员中非常受欢迎,这很有趣。 我谨将这篇文章献给 Chris M 和过去几年参与出色托盘图标类项目的其他人。
将图标添加到你的项目
Ctrl-Shift-A 将弹出“添加新项”对话框。 从可用模板列表中选择“图标文件”。 如果列表太长,请从左侧的树控件中选择“资源”。 这将在右侧显示一个较小的列表,您可以更轻松地选择“图标文件”。 现在单击“打开”。 你将得到 VS.NET 图标编辑器。 现在,你可以在此处创建你的图标,或者从其他位置复制/粘贴一个图标。
现在,右键单击“解决方案资源管理器”中的此图标。 选择“属性”。 并将“生成操作”属性更改为“嵌入的资源”。 这将指示编译器将此图标与你的 EXE 文件一起嵌入,从而免去你必须将图标与 EXE 一起分发的麻烦。
将 NotifyIcon 成员添加到你的窗体
好的。 现在我们准备好了图标,我们需要将其添加到我们的窗体类中。
private NotifyIcon m_notifyicon;
好了,我们已经添加了一个 NotifyIcon 成员。 现在让我们初始化它并设置一些默认属性。 这应该从窗体对象的构造函数中完成。
m_notifyicon = new NotifyIcon();
m_notifyicon.Text = "Hello, what's cooking?";
m_notifyicon.Visible = true;
m_notifyicon.Icon = new Icon(GetType(),"Icon1.ico"); //Thanks to Hasaki for this.
好了,现在编译并运行你的程序。 你会在托盘中看到该图标。 这相当简单,不是吗? 但是通常人们喜欢向他们的托盘图标添加上下文菜单。 仅仅坐在那里的托盘图标不是很实用。
将上下文菜单添加到托盘图标
我们需要做的第一件事是将 ContextMenu 成员添加到我们的窗体。
private ContextMenu m_menu;
现在我们需要初始化它并添加一些菜单项。
m_menu = new ContextMenu();
m_menu.MenuItems.Add(0,
new MenuItem("Show",new System.EventHandler(Show_Click)));
m_menu.MenuItems.Add(1,
new MenuItem("Hide",new System.EventHandler(Hide_Click)));
m_menu.MenuItems.Add(2,
new MenuItem("Exit",new System.EventHandler(Exit_Click)));
我们添加了三个菜单项,并且还为每个菜单项关联了单击事件处理程序。 我可以创建一个 MenuItem 对象数组,但这里真的不需要。
现在我们需要将此 ContextMenu 与我们的托盘图标关联起来。 所以我们这样做。
m_notifyicon.ContextMenu = m_menu;
现在让我们填充这些事件处理程序。
protected void Exit_Click(Object sender, System.EventArgs e)
{
Close();
}
protected void Hide_Click(Object sender, System.EventArgs e)
{
Hide();
}
protected void Show_Click(Object sender, System.EventArgs e)
{
Show();
}
好的。 编译并运行它。 现在右键单击托盘图标会弹出上下文菜单。 你可以使用这两个菜单选项隐藏和显示窗体窗口。 “退出”选项将退出应用程序。
一个小问题
现在你会注意到一个轻微的烦恼。 当你退出程序时,托盘图标不会消失。 但是当你将鼠标移动到托盘上时,该图标会消失。 那么,我们如何避免这种情况? 同样,与整个 .NET 的其他一切一样,它就像 1、2、3 一样简单。 重写窗体对象的 Dispose 函数并将以下代码行放入其中。
protected override void Dispose( bool disposing )
{
if( disposing )
{
this.m_notifyicon.Dispose(); //we dispose our tray icon here
}
base.Dispose( disposing );
}
完整源代码列表
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Data;
namespace TrayTest
{
public class Form1 : System.Windows.Forms.Form
{
private NotifyIcon m_notifyicon;
private ContextMenu m_menu;
public Form1()
{
Text = "TrayIcon test program";
m_menu = new ContextMenu();
m_menu.MenuItems.Add(0,
new MenuItem("Show",new System.EventHandler(Show_Click)));
m_menu.MenuItems.Add(1,
new MenuItem("Hide",new System.EventHandler(Hide_Click)));
m_menu.MenuItems.Add(2,
new MenuItem("Exit",new System.EventHandler(Exit_Click)));
m_notifyicon = new NotifyIcon();
m_notifyicon.Text = "Right click for context menu";
m_notifyicon.Visible = true;
m_notifyicon.Icon = new Icon(GetType(),"Icon1.ico");
m_notifyicon.ContextMenu = m_menu;
}
protected void Exit_Click(Object sender, System.EventArgs e)
{
Close();
}
protected void Hide_Click(Object sender, System.EventArgs e)
{
Hide();
}
protected void Show_Click(Object sender, System.EventArgs e)
{
Show();
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
this.m_notifyicon.Dispose();
}
base.Dispose( disposing );
}
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
}
}
结论
我要感谢 James Johnson 在我努力将图标嵌入到我的 exe 中时给我的宝贵提示。 还要特别感谢 Colin,感谢他在我因使用新 CD 刻录机的不良经历而陷入绝望时,用 Bobs 让我振作起来。