65.9K
CodeProject 正在变化。 阅读更多。
Home

CTrayIcon - 系统托盘图标包装器

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.17/5 (14投票s)

2004 年 8 月 23 日

8分钟阅读

viewsIcon

192651

downloadIcon

5083

一篇展示系统任务栏图标包装类的文章。

Screenshot - CTrayIcon_1.gif

引言

系统托盘图标通知区域——或称“系统托盘”或“任务栏通知系统区域”——是 Microsoft Windows 桌面用户界面中任务栏的一部分。该区域显示时钟和某些程序的图标,以便用户能够持续地注意到它们的存在并可以轻松地点击其中任何一个。不幸的是,MFC 没有提供一个类来包装系统托盘的功能。因此,我决定编写一个并公开发布。

背景

系统托盘是 Windows 9x 和 NT(家族)版本任务栏一端的区域。通常安装在系统托盘中的图标包括声音的音量控制、防病毒软件和系统资源指示器。当系统托盘中安装的图标多于可用空间时,系统托盘将变得可以水平滚动或扩展。要与系统托盘中的程序交互,请用鼠标选择图标,然后双击或右键单击该图标。使用程序后将其最小化时,它将缩小到系统托盘中,而不是缩小到任务栏的主区域。

系统托盘图标的特殊之处在于,当安装时,它可以在鼠标悬停在其上时显示自定义消息。右键单击时出现的菜单可以自定义,双击时发生的操作也可以自定义。例如,Internet Explorer 的双击操作可以是启动(启动或打开程序窗口)该程序,但桌面图标的双击操作可以是“查看桌面”,即移除活动窗口并显示下方的桌面。

程序安装时可以通过在系统注册表中创建条目,将图标放置在系统托盘中。也可以通过创建程序的快捷方式并将快捷方式图标拖到系统托盘中来放置。删除图标可以通过删除注册表项或右键单击图标并从弹出菜单中选择“删除”来完成。时钟图标可以通过在任务栏属性中取消选中“显示时钟”选项来删除。

关于 CTrayIcon

JTray Menu Screenshot - Metal MenuCTrayIcon 让 VC++ 开发者能够将图标添加到 Windows 系统托盘。这可以快速地让任何 VC++ 应用程序对 Windows 用户更具吸引力和直观性。

CTrayIcon 可以显示弹出式菜单。这使得开发者可以修改外观和感觉,并添加强大的菜单项。

JTray Balloon Message Screenshot 使用 CTrayIcon,托盘图标可以拥有在鼠标悬停时出现的工具提示文本。此外,还提供了一个酷炫的鼠标悬停效果。

CTrayIcon 类摘要

此类是围绕系统托盘图标通知的包装。它将一组指定的图标对——即图标和悬停图标——以及工具提示添加到系统托盘通知区域,并提供一个回调通知处理程序用于鼠标消息处理。

CTrayIcon 构造

语法

// Use if notification messages are to be 
// sent to the parent window. 
CTrayIcon(
    CWnd *pWnd,
    unsigned int uNotificationMessage,
    MouseMsgHandlerPtr *pMouseMsgHandler,
    unsigned int uHandlersCount,
    IconDataPtr *pIconData,
    unsigned int uIconsCount,
    int nSelectedIconIndex,
    unsigned int uElapsed
    );

// Use if notification messages are to 
// be sent to the CTrayIcon class.
CTrayIcon(
    MouseMsgHandlerPtr *pMouseMsgHandler,
    unsigned int uHandlersCount,
    IconDataPtr *pIconData,
    unsigned int uIconsCount,
    int nSelectedIconIndex,
    unsigned int uElapsed
    );

参数

  • pWnd: 指向接收与任务栏状态区域图标相关的通知消息的窗口的指针。如果未提供 pWnd 参数,则每当图标发送通知消息时,都会调用 CTrayIcon::OnNotifyIcon 函数。
  • uNotificationMessage: 用于处理与任务栏状态区域图标相关的适当鼠标通知消息的消息标识符。如果未提供 uNotificationMessage 参数,则将注册一个新窗口消息——即 ::RegisterWindowMessage(_T("NotifyIcon")——并将其用作默认通知消息标识符。
  • pMouseMsgHandlerPtr: 指向派生自 CTrayIconMouseMsgHandler 的类的对象的指针数组,用于处理鼠标消息。
  • uHandlersCount: 指示 pMouseMsgHandlerPtr 指向的数组中的处理程序数量。
  • pIconDataPtr: 指向 CIconData 对象的指针数组——即图标、悬停图标和工具提示单元——将添加到任务栏状态区域。
  • uIconsCount: 指示 pIconDataPtr 指向的数组中的图标数量。
  • nSelectedIconIndex: pIconDataPtr 指向的数组中选定图标的索引。
  • uElapsed: 指示任务栏状态区域图标动画计时器的经过时间。

CTrayIcon 获取器和设置器

// Sets the notification message target window
void SetTargetWnd(CWnd *pWnd);

// Sets the notification message identifier
void SetNotificationMsg(unsigned
int uNotificationMsg);

// Sets the selected icon index
void SetSelectedIconIndex(int nIconIndex);

// Gets the selected icon index
int GetSelectedIconIndex() const;

// Sets the mouse message handler
void SetMouseMsgHandler(
    MouseMsgHandlerPtr *pMouseMsgHandler, 
    unsigned int uHandlersCount);

// Gets the mouse message handler
MouseMsgHandlerPtr* GetMouseMsgHandler()
const;

// Sets timer elapse
void SetTimerElapse(unsigned int uElapse);

// Gets timer elapse
int GetTimerElapse() const;

// Sets icon data
void SetIconData(IconDataPtr *pIconData, unsigned
int uIconsCount);

// Gets icons data
IconDataPtr* GetIconData()
const;

// Indicates whether animation is in progress
BOOL IsAnimating () const ;  

CTrayIcon 方法

// Dispalys a hidden icon
BOOL ShowIcon();

// Hides a visible icon
BOOL HideIcon();

// Refreshes icon
BOOL RefreshIcon();

// Shows the hover icon
BOOL HoverIcon();

// Starts icon animation
BOOL StartIconAnimation();

// Stops icon animation
BOOL StopIconAnimation();

CTrayIcon 事件和回调

OnTaskBarCreated

用于处理 WM_TI_TASKBARCREATED 消息,以验证任务栏状态图标的创建。

语法

// Callback handler for the taskbar created event 
LRESULT OnTaskBarCreated( 
    WPARAM wParam, 
    LPARAM lParam 
    ); 

结果

验证后返回 LRESULT

OnNotifyIcon

用于处理 WM_TI_NOITIFYICON 消息,以进行适当的鼠标消息处理。

语法

// Default callback handler for 
// taskbar notification message event 
LRESULT OnNotifyIcon(
    WPARAM wParam, 
    LPARAM lParam 
    ); 

结果

验证后返回 LRESULT

WindowProc

CTrayIcon 对象提供一个 Windows 过程。WindowProc 函数是一个应用程序定义的函数,用于处理发送到窗口的消息。

语法

// Callback handler for the window procedure 
LRESULT WindowProc( 
    unsigned int uMsg, 
    WPARAM wParam, 
    LPARAM lParam 
    );

结果

验证后返回 LRESULT

OnTimer

用于处理 WM_TIMER 消息,该消息在经过指定时间后触发。

语法

// Callback handler for the timer elapsed event 
void OnTimer( 
    unsigned int uIDEvent 
    );

CTrayIconMouseMsgHandler 类摘要

此类是用于处理鼠标通知消息的抽象基类。派生自 CTrayIconMouseMsgHandler 的类应处理鼠标通知消息,并且必须实现纯虚函数 MouseMessageHandler()

CTrayIconMouseMsgHandler 构造

仅提供一个单参数构造函数,该构造函数接受一个窗口消息,并将其与接收其他系统托盘图标通知消息相关联。

语法

// Single paramenter constructor, a 
// mosue message identfier has to be passed
CTrayIconMouseMsgHandler( 
    unsigned int uMouseMsgID 
    );

参数

uMouseMsgID:当用户在系统托盘图标上执行任何鼠标操作时,操作系统生成的 Windows 消息。例如,鼠标按钮的按下或释放等。

CTrayIconMouseMsgHandler 获取器和设置器

// Gets the mouse message identifier 
unsigned int GetMouseMsgID() const; 

// Sets the mosue message identifier 
void SetMouseMsgID(
    unsigned int uMouseMsgID
    );

CTrayIconMouseMsgHandler 事件和回调

MouseMsgHandler

此方法是一个纯虚方法,必须在派生类中定义,用于处理系统托盘图标鼠标通知消息。此事件由 CTrayIcon::OnNotifyIcon() 方法生成。

语法

// Pure-virtual callback mouse message handler, 
// necessary to be implemented by the derived class, 
// for handling system tray icon notifications. 
virtual void MouseMsgHandler() = 0;

CTrayIconMouseMsgHandler 同义词

MouseMsgHandlerPtr

// Synomym for CTrayIconMouseMsgHandler pointer 
typedef CTrayIconMouseMsgHandler* MouseMsgHandlerPtr;

CIconData 类摘要

此类封装了一组图标对——即图标和悬停图标——以及系统托盘通知区域的工具提示。它封装了在图标和悬停图标之间切换,以及在两个不同的 CIconData 对象及其各自工具提示之间切换的基本功能。

CIconData 构造

对于对象创建,提供了一个四参数构造函数,它接受图标对(图标和悬停图标)标识符——其中悬停图标是可选的——以及一个工具提示和一个可选的图标处理程序。

语法

// Quad parameter constructor 
CIconData(
    unsigned int uDefaultIconID, 
    LPSTR lpToolTip,
    unsigned int uHoverIconID = 0, 
    HICON hIcon = NULL
    );

// Copy constructor
CIconData(
    const CIconData &pIconData
    );

参数

  • uDefaultIconID:应用程序定义的图标标识符,将显示在系统托盘图标通知区域。
  • lpToolTip:指向以 NULL 结尾的字符串的指针,其中包含标准工具提示的文本。最多可以包含 64 个字符,包括终止的 NULL
  • uHoverIconID:应用程序定义的图标标识符,将在鼠标悬停期间显示在系统托盘图标通知区域。
  • hIcon:要添加、修改或删除的图标句柄。为避免图标失真,请注意,在不同版本的 Microsoft® Windows® 下,通知区域图标的支持级别不同。Windows 95、Windows 98 和 Microsoft Windows NT® 4.0 支持最多 4 位/像素 (BPP) 的图标。Windows Millennium Edition (Windows Me) 和 Windows 2000 支持的图标颜色深度最高可达当前显示模式。Windows XP 支持最高 32 BPP 的图标。

CIconData 获取器和设置器

// Gets the selected icon's identifer
unsigned int GetIconID() const;

// Gets the default icon identfier
unsigned int GetDefaultIconID() const;

// Sets the default icon identifier
void SetDefaultIconID(unsigned int uIconID);

// Gets the hover icon identifer
unsigned int GetHoverIconID() const;

// Sets the hover icon identifier
void SetHoverIconID(unsigned int uIconID);

// Gets the tooltip
LPSTR GetToolTip() const;

// Sets the tooltip
void SetToolTip(LPSTR lpToolTip);

// Gets the icon handler
HICON GetIconHandler() const;

CIconData 方法

// Selects and loads the speciifed icon into memory
bool LoadIcon(unsigned int uIconID);

CIconData 同义词

IconDataPtr

// Synomym for CIconData pointer 
typedef CIconData* IconDataPtr;

如何使用

让我们一步一步来完成任务。

步骤 1 - 开始

创建一个应用程序,并将 TrayIcon.hTrayIcon.cppTrayIconMouseMsgHandler.hIconData.hUtilities.hMouseMsgHandlerImpl.h 文件添加到项目中。

步骤 2 - 预先确保可重用性

在项目中设置一个全局头文件库,其中包含可在任何地方使用的可重用实用工具方法,这总是很有益的。

// Utilities functions

// Shows a window
BOOL ShowWnd(CWnd* pWnd)
{
    return pWnd->ShowWindow(SW_SHOW);
}

// Hides a window
BOOL HideWnd(CWnd* pWnd)
{
    return pWnd->ShowWindow(SW_HIDE);
}

// Shows a popup menu
void ShowPopupMenu(CWnd* pWnd, 
    unsigned int uResourseID, int nSubMenuPos)
{
    CPoint aPos;
    GetCursorPos(&aPos);
    CMenu aMenu;
    aMenu.LoadMenu(uResourseID);
    aMenu.GetSubMenu(nSubMenuPos)->TrackPopupMenu(
        TPM_RIGHTALIGN | TPM_RIGHTBUTTON, 
        aPos.x, 
        aPos.y, 
        pWnd, 
        0
        );
}

步骤 3 - 设置鼠标消息处理程序

在此阶段,我们将设置几个派生自 CTrayIconMouseMsgHandler 的类来处理鼠标通知消息。

设置左键双击消息处理程序

// Left mouse button double click message handler
class CLeftMouseDblClickMsgHandler: public CTrayIconMouseMsgHandler
{
    public:

    CLeftMouseDblClickMsgHandler() : CTrayIconMouseMsgHandler(
        WM_LBUTTONDBLCLK){}

    void MouseMsgHandler()
    {
        ShowWnd(AfxGetMainWnd());
    }
};

设置右键单击消息处理程序

// Right mouse button click message handler
class CRightMouseClickMsgHandler: public CTrayIconMouseMsgHandler
{
    public:

    CRightMouseClickMsgHandler() : CTrayIconMouseMsgHandler(
        WM_RBUTTONDOWN){}

    void MouseMsgHandler()
    {
        ShowPopupMenu(AfxGetMainWnd(), IDR_TASKBAR_MENU, 0);
    }
};

设置鼠标悬停消息处理程序

// Mouse hover message handler
class CMouseHoverMsgHandler: public CTrayIconMouseMsgHandler
{
    public:

    CMouseHoverMsgHandler(CTrayIcon* pTrayIcon) : CTrayIconMouseMsgHandler(
        WM_MOUSEFIRST)
    {
        m_pTrayIcon = pTrayIcon;
    }

    void SetTrayIcon(CTrayIcon* pTrayIcon)
    {
        m_pTrayIcon = pTrayIcon;
    }

    void MouseMsgHandler()
    {
        m_pTrayIcon->HoverIcon();
    }

    private:
    CTrayIcon* m_pTrayIcon;
};

步骤 4 - 声明

在您的类中添加一个指向 CTrayIcon 的成员。

// Declarying CTrayIcon object pointer for adding an icon to 
// the system tray notification area
CTrayIcon* m_pTrayIcon;

步骤 5 - 初始化

在此阶段,我们将初始化 CTrayIcon 对象以将图标添加到系统托盘通知区域。

// Declare an array of MouseMsgHandlerPtr of size 3, 
// to handle three types of mouse events
MouseMsgHandlerPtr *pHandler = new MouseMsgHandlerPtr [3];

// Define an object for handling right mouse button click events
MouseMsgHandlerPtr rbcHandler = new CRightMouseClickMsgHandler();

// Define an object for handling left mouse button double click events
MouseMsgHandlerPtr lbcHandler = new CLeftMouseDblClickMsgHandler();

// Define an object for handling mouse hover events
MouseMsgHandlerPtr mhHandler = new CMouseHoverMsgHandler(m_pTrayIcon);

pHandler[0] = lbcHandler;
pHandler[1] = rbcHandler;
pHandler[2] = mhHandler;

// Declare an array of IconDataPtr of size 2, to add two sets of icons. 
// Only one will be active though.
IconDataPtr *pIconData = new IconDataPtr[2];

// Define an object of Blue MFC icon
pIconData[0] = new CIconData(IDR_MAINFRAME, _T("CTrayIcon Blue Demo"), 
    IDR_MAINFRAME_HOVER);

// Define an object of Green MFC icon
pIconData[1] = new CIconData(
    IDR_MAINFRAME_GREEN, _T("CTrayIcon Green Demo"), IDR_MAINFRAME_HOVER);

// Define the CTrayIcon object
m_pTrayIcon = new CTrayIcon(pHandler, 3, pIconData, 2, 0, SECOND);

// Refer the CTrayIcon object to the CMouseHoverMsgHandler object, 
// for handling mouse events
((CMouseHoverMsgHandler*)mhHandler)->SetTrayIcon(m_pTrayIcon);

步骤 6 - 设置功能

在此阶段,我们将设置隐藏、显示和动画系统托盘通知图标的功能。

显示托盘通知图标

void CCTrayIconDemoDlg::OnBnClickedBtnshowicon()
{
    m_pTrayIcon->ShowIcon();
}

隐藏托盘通知图标

void CCTrayIconDemoDlg::OnBnClickedBtnhideicon()
{
    m_pTrayIcon->HideIcon();
}

启动托盘通知图标动画

void CCTrayIconDemoDlg::OnBnClickedBtnstartani()
{
    m_pTrayIcon->StartIconAnimation();
}

停止托盘通知图标动画

void CCTrayIconDemoDlg::OnBnClickedBtnstopani()
{
    m_pTrayIcon->StopIconAnimation();
}

将窗口最小化到托盘通知图标

void CCTrayIconDemoDlg::OnBnClickedBtnminimize()
{
    m_pTrayIcon->ShowIcon();
    HideWnd(this);
}

从托盘通知图标显示窗口

void CCTrayIconDemoDlg::OnShow() 
{
    ShowWnd(this);
}

步骤 7 - 最后润色

完成后,我们将优雅地释放资源。

void CCTrayIconDemoDlg::OnCancel() 
{
    delete m_pTrayIcon;
    CDialog::OnCancel();
}

替代步骤 - 另一种方法

在上述步骤中,我们看到了如何使用 CTrayIcon 类高效地处理系统托盘通知图标消息。如果您想在自己的 CWnd 类中处理这些消息怎么办?如果您想在 CWndCDialog 类中处理系统托盘通知图标消息,请实现此阶段。在此示例中,该类将是 CCTrayIconDemoDlg 类。转到头文件并注册一个窗口消息,以便在系统托盘图标创建后进行处理。

const unsigned int WM_TI_NOTIFYICON = 
    ::RegisterWindowMessage(_T("TaskBarCreated"));

转到 AFX_MSG 并将以下行添加为粗体

//{{AFX_MSG(CCTrayIconDemoDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnNotifyIcon(WPARAM wp, LPARAM lp);
//}}AFX_MSG

然后转到 AFX_MSG_MAP 并将以下行添加为粗体

//{{AFX_MSG_MAP(CCTrayIconDemoDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_REGISTERED_MESSAGE(WM_TI_NOTIFYICON, OnNotifyIcon)
//}}AFX_MSG_MAP

CTrayIcon 对象创建替换为以下代码。

// Define the CTrayIcon object
m_pTrayIcon = new CTrayIcon(
    this, WM_TI_NOTIFYICON, pHandler, 
    3, pIconData, 2, 0, SECOND);

最后,重定向到 CTaskIcon 方法。

void CCTrayIconDemoDlg::OnNotifyIcon(WPARAM wParam, LPARAM lParam) 
{ 
    // TODO
    m_pTrayIcon->OnNotifyIcon(wParam, lParam);
}

历史

  • 2004 年 8 月 23 日 -- 发布了原始版本
  • 2007 年 6 月 6 日 -- 更新了文章和下载
© . All rights reserved.