西安二炮工程学院 俞俊军 张 毅
摘要
本文对如何将应用程序的图标加入到Windows的系统托盘中做了较为详细的介绍,
然后给出了一个C++类以方便的实现该功能,并在VC++6.0中给出了一个应用程序
实例来体现其具体实现过程。同时该应用程序实例还讲解了如何在托盘中实现动
画图标以及在程序中关闭计算机的技术。
关键词:系统托盘 动画图标
Windows98桌面的系统托盘位于任务栏的右侧,即Windows98桌面的右下方。它常
用来显示一些系统的状态。如:系统时间,音量控制以及其它的一些图标(依个
人机器安装的软件而不定),如下图为笔者的Windows98系统托盘。(图略)
常常能见到一些优秀的软件在运行后会将其应用程序图标加入到系统托盘中,如
金山词霸。如果能将自己编写的应用程序的图标也加入到系统托盘中,将会使你
的程序显得很有专业水准。
其实这并不困难,与系统托盘通信的函数只有一个:
Shell_NotifyIcon (UINT message, NOTIFYICONDATA &m_nid);
首先看一下该函数的两个参数。
第一个参数message可以取以下值:
NIM_ADD 向托盘中加入一个图标;
NIM_MODIFY 修改托盘中的图标
NIM_DELETE 从托盘中删除一个图标
第二个参数m_nid是NOTIFYICONDATA结构的一个引用。该结构的原型如下:
typedef struct _NOTIFYICONDATA
{
DWORD cbSize;// 结构的大小,必须在程序中给出
HWND hWnd;
//是你程序中将要接收托盘消息的窗口句柄
UINT uID;
// 应用程序中定义的托盘图标ID,此参数用作标识
UINT uFlags;
//设置属性,低三位有意义,0--7,如下:
//第一位//#define NIF_MESSAGE 0x1
// uCallbackMessage参数有效
//第二位//#define NIF_ICON 0x2 // hIcon参数有效
//第三位//#define NIF_TIP 0x4 // szTip参数有效
UINT uCallbackMessage;
// 自定义的消息ID值,一定不要与以有的消息ID相重。
HICON hIcon;
//显示在系统托盘上的Icon的句柄,可以为系统的 IDI_WINLOGO等
CHAR szTip[64]; // 用于图标显示的提示字符串
} NOTIFYICONDATA;
为了接收到来自托盘的通知消息你可以将uCallbackMessage设定为你所定义的消息
ID值,同时设定NIF_MESSAGE标志。这样当用户在你的托盘图标上移动或按下鼠标
时,Windows将发出消息:该消息的 messageID是你在uCallbackMessage中定义的
值;wParam是你定义的uID值;而lParam是鼠标事件(如WM_LBUTTONDOWN),这样你
的应用程序就能响应该事件了。
因此,为了将自己的应用程序加入到系统托盘中,首先得建立一处理托盘通知消息
的窗口对象,然后将窗口对象与你自己的托盘通知消息联系起来并建立相应的托盘
通知消息映射机制,以便你的窗口对象能处理相应的事件。
可以看到结构体NOTIFYICONDATA中,其成员变量hWnd,uID,uFlags均用于在窗口对
象与你自己的托盘通知消息之间建立联系,而成员变量uCallbackMessage则必须是
对应于你的窗口对象的托盘通知消息ID值。
于是要完成的工作有:
(1)建立一处理托盘通知消息的窗口对象;
(2)建立一结构体NOTIFYICONDATA变量,并给变量的相应域赋值以在托盘通知消
息与窗口对象之间建立联系;
(3)建立相应的托盘通知消息映射机制;
(4)调用Shell_NotifyIcon函数以在系统托盘中加入、修改或删除图标;
(5)当然别忘了在你的窗口对象中编写相应的事件响应函数。
因此,可以编写一C++类来实现以上功能以简化编程同时提高代码的可重用性。以
下为该类代码:
class CTrayIcon : public CCmdTarget {
protected:
DECLARE_DYNAMIC(CTrayIcon)
NOTIFYICONDATA m_nid;
// Shell_NotifyIcon 函数中的结构参数
public:
CTrayIcon(UINT uID);
~CTrayIcon();
// 通过调用该成员函数来接收托盘通知消息
void SetNotificationWnd(CWnd* pNotifyWnd,
UINT uCbMsg);
// SetIcon 函数用来在系统托盘中加入、改变及删除图标。
//要删除图标这样调用:SetIcon(0)
BOOL SetIcon(UINT uID);
BOOL SetIcon(HICON hicon, LPCSTR lpTip);
BOOL SetIcon(LPCTSTR lpResName, LPCSTR lpTip)
{
return SetIcon(lpResName ?
AfxGetApp()->LoadIcon(lpResName):NULL,lpTip);
}
BOOL SetStandardIcon(LPCTSTR lpszIconName,LPCSTR lpTip)
{
return SetIcon(::LoadIcon(NULL,lpszIconName),lpTip);
}
virtual LRESULT OnTrayNotification(WPARAM uID, LPARAM lEvent);
};
CTrayIcon::CTrayIcon(UINT uID)
{
//初始化NOTIFYICONDATA结构变量
memset(&m_nid, 0 , sizeof(m_nid));
m_nid.cbSize = sizeof(m_nid);
m_nid.uID = uID;
AfxLoadString(uID, m_nid.szTip, sizeof
(m_nid.szTip));
}
CTrayIcon::~CTrayIcon()
{
SetIcon(0); // 从系统托盘中删除图标
}
// 设定通知窗口,该窗口必须已被创建