/*-------------------------------------------------------------------------
* Copyright (c) 2004, Ferri Weng
* All Lefts reserved.
*
* 文件名称:TrayIcon.h
* 文件标识:_TRAYICON_H
* 摘 要:定义一个 CTrayIcon 类,以实现托盘功能。
*
* 当前版本:1.0
* 作 者:Ferri Weng
* 完成日期:2004-09-17
*
* 使用方法:
*
* 1. 定义资源:
* - 在工程资源中定义托盘所用到的弹出菜单、ICO、说明文串,并为弹出菜单编程
* - 为托盘自定义一个消息 (例: 在StdAfx.h中添加: WM_MY_TRAYMSG WM_USER + 100)
*
* 2. 添加CTrayIcon类到工程:
* - 将 TrayIcon.h 添加到所要使用的工程中去,一般是主窗体的头文件中 (例:MainFrm.h)
* - 在工程中添加CTrayIcon 变量 (如在CMainFrame中添加 CTrayIcon trayIcon;)
*
* 3. 消息:
* - 为使用的窗体添加消息映射以及消息映射函数:
* ON_MESSAGE(WM_TRAY_THEMSG, OnTrayNotification)
* 在OnTrayNotification函数中,必需调用 m_trayIcon.OnTrayNotification(uID, lEvent);
*
* 4. 使用:
* - 用 Create 函数在适当的位置进行初始化(如 OnCreate 函数中)
* - 用 SetXXX 函数进行设置
* - 用 EnableTray() 进行托盘工具的显示与隐藏
*
*------------------------------------------------------------------------*/
#ifndef _TRAYICON_H
#define _TRAYICON_H
#if _MSC_VER > 1000
#pragma once
#endif
class CTrayIcon : public CCmdTarget
{
protected:
DECLARE_DYNAMIC(CTrayIcon)
public:
CTrayIcon();
~CTrayIcon();
void Create(CWnd* pNotifyWnd, UINT uMsgID, UINT uMenuID = 0, UINT uIcoID = 0, UINT uTipID = 0);
void Create(CWnd* pNotifyWnd, UINT uMsgID, UINT uMenuID, UINT uIcoID, char* szTipText);
void SetIcon(UINT uID); //设置ICON
void SetIcon(LPCTSTR lpszIconName); //设置ICON
void SetIcon(HICON hicon); //设置ICON
void SetTipText(LPCSTR lpTipText); //设置说明文本
void SetTipText(UINT uID); //设置说明文本
void SetMenu(UINT uID); //设置弹出菜单
BOOL EnableTray(BOOL bShow = TRUE); //是/否在托盘区显示图标
void SetNotificationWnd(CWnd* pNotifyWnd, UINT uMsgID);
virtual LRESULT OnTrayNotification(WPARAM uID, LPARAM lEvent);
public:
BOOL m_bShutdown; //提供外部程序一个用来标志程序是否可以关闭的标识
private:
NOTIFYICONDATA m_nDATA;
HICON m_icon;
};
#endif
* Copyright (c) 2004, Ferri Weng
* All Lefts reserved.
*
* 文件名称:TrayIcon.h
* 文件标识:_TRAYICON_H
* 摘 要:定义一个 CTrayIcon 类,以实现托盘功能。
*
* 当前版本:1.0
* 作 者:Ferri Weng
* 完成日期:2004-09-17
*
* 使用方法:
*
* 1. 定义资源:
* - 在工程资源中定义托盘所用到的弹出菜单、ICO、说明文串,并为弹出菜单编程
* - 为托盘自定义一个消息 (例: 在StdAfx.h中添加: WM_MY_TRAYMSG WM_USER + 100)
*
* 2. 添加CTrayIcon类到工程:
* - 将 TrayIcon.h 添加到所要使用的工程中去,一般是主窗体的头文件中 (例:MainFrm.h)
* - 在工程中添加CTrayIcon 变量 (如在CMainFrame中添加 CTrayIcon trayIcon;)
*
* 3. 消息:
* - 为使用的窗体添加消息映射以及消息映射函数:
* ON_MESSAGE(WM_TRAY_THEMSG, OnTrayNotification)
* 在OnTrayNotification函数中,必需调用 m_trayIcon.OnTrayNotification(uID, lEvent);
*
* 4. 使用:
* - 用 Create 函数在适当的位置进行初始化(如 OnCreate 函数中)
* - 用 SetXXX 函数进行设置
* - 用 EnableTray() 进行托盘工具的显示与隐藏
*
*------------------------------------------------------------------------*/
#ifndef _TRAYICON_H
#define _TRAYICON_H
#if _MSC_VER > 1000
#pragma once
#endif
class CTrayIcon : public CCmdTarget
{
protected:
DECLARE_DYNAMIC(CTrayIcon)
public:
CTrayIcon();
~CTrayIcon();
void Create(CWnd* pNotifyWnd, UINT uMsgID, UINT uMenuID = 0, UINT uIcoID = 0, UINT uTipID = 0);
void Create(CWnd* pNotifyWnd, UINT uMsgID, UINT uMenuID, UINT uIcoID, char* szTipText);
void SetIcon(UINT uID); //设置ICON
void SetIcon(LPCTSTR lpszIconName); //设置ICON
void SetIcon(HICON hicon); //设置ICON
void SetTipText(LPCSTR lpTipText); //设置说明文本
void SetTipText(UINT uID); //设置说明文本
void SetMenu(UINT uID); //设置弹出菜单
BOOL EnableTray(BOOL bShow = TRUE); //是/否在托盘区显示图标
void SetNotificationWnd(CWnd* pNotifyWnd, UINT uMsgID);
virtual LRESULT OnTrayNotification(WPARAM uID, LPARAM lEvent);
public:
BOOL m_bShutdown; //提供外部程序一个用来标志程序是否可以关闭的标识
private:
NOTIFYICONDATA m_nDATA;
HICON m_icon;
};
#endif
#include "stdafx.h"
#include "TrayIcon.h"
#include <afxpriv.h>
IMPLEMENT_DYNAMIC(CTrayIcon, CCmdTarget)
//
CTrayIcon::CTrayIcon()
{
memset(&m_nDATA, 0 , sizeof(m_nDATA));
m_nDATA.cbSize = sizeof(m_nDATA);
m_nDATA.uFlags = NIF_TIP|NIF_MESSAGE|NIF_ICON;
m_icon = NULL;
m_bShutdown = FALSE;
}
CTrayIcon::~CTrayIcon()
{
SetIcon((HICON)NULL);
EnableTray(FALSE);
m_icon = NULL;
}
//
// 初化化一个TrayIcon对象
void CTrayIcon::Create(CWnd* pNotifyWnd, //要关联的窗体
UINT uMsgID, //消息号
UINT uMenuID, //菜单资源编号
UINT uIcoID, //图标资源编号
UINT uTipID) //说明文本信号资源编号
{
ASSERT(::IsWindow(pNotifyWnd-> GetSafeHwnd()));
ASSERT(uMsgID > = WM_USER);
m_nDATA.hWnd = pNotifyWnd-> GetSafeHwnd();
m_nDATA.uCallbackMessage = uMsgID;
if(0 != uMenuID) SetMenu(uMenuID);
if(0 != uIcoID) SetIcon(uIcoID);
if(0 != uTipID) SetTipText(uTipID);
}
//
// 初化化一个TrayIcon对象
void CTrayIcon::Create(CWnd* pNotifyWnd, //要关联的窗体
UINT uMsgID, //消息号
UINT uMenuID, //菜单资源编号
UINT uIcoID, //图标资源编号
char* szTipText) //说明文本字串
{
ASSERT(::IsWindow(pNotifyWnd-> GetSafeHwnd()));
ASSERT(uMsgID > = WM_USER);
m_nDATA.hWnd = pNotifyWnd-> GetSafeHwnd();
m_nDATA.uCallbackMessage = uMsgID;
if(0 != uMenuID) SetMenu(uMenuID);
if(0 != uIcoID) SetIcon(uIcoID);
if(NULL != szTipText) SetTipText(szTipText);
}
//
// 根据资源ID,设置托盘区的图标
inline void CTrayIcon::SetIcon(UINT uID)
{
if(0 != uID)
{
m_icon = AfxGetApp()-> LoadIcon(uID);
m_nDATA.uFlags &= ~NIF_ICON;
if(NULL != m_icon) m_nDATA.uFlags |= NIF_ICON;
}
}
//
// 根据ICON名称,设置托盘区的图标
inline void CTrayIcon::SetIcon(LPCTSTR lpszIconName)
{
if((NULL != lpszIconName) && ( '\0 ' != lpszIconName[0]))
{
m_icon = ::LoadIcon(NULL, lpszIconName);
m_nDATA.uFlags &= ~NIF_ICON;
if(NULL != m_icon) m_nDATA.uFlags |= NIF_ICON;
}
}
//
// 根据ICON的句柄,设置托盘区的图标
inline void CTrayIcon::SetIcon(HICON hicon)
{
m_icon = hicon;
m_nDATA.uFlags &= ~NIF_ICON;
if(NULL != m_icon) m_nDATA.uFlags |= NIF_ICON;
}
//
// 根据工程的菜单的资源号,设置弹出菜单
inline void CTrayIcon::SetMenu(UINT uID)
{
m_nDATA.uID = uID;
}
//
// 根据资源号,设置提示文本
inline void CTrayIcon::SetTipText(UINT uID)
{
AfxLoadString(uID, m_nDATA.szTip, sizeof(m_nDATA.szTip));
m_nDATA.uFlags &= ~NIF_TIP;
if (m_nDATA.szTip[0] != '\0 ') m_nDATA.uFlags |= NIF_TIP;
}
//
// 设置提示文本
inline void CTrayIcon::SetTipText(LPCSTR lpTipText)
{
strncpy(m_nDATA.szTip, lpTipText, sizeof(m_nDATA.szTip));
m_nDATA.uFlags &= ~NIF_TIP;
if (m_nDATA.szTip[0] != '\0 ') m_nDATA.uFlags |= NIF_TIP;
}
//
// 设置关联窗体与消息号
void CTrayIcon::SetNotificationWnd(CWnd* pNotifyWnd, UINT uMsgID)
{
ASSERT(NULL != pNotifyWnd);
ASSERT(::IsWindow(pNotifyWnd-> GetSafeHwnd()));
ASSERT(uMsgID > = WM_USER);
m_nDATA.hWnd = pNotifyWnd-> GetSafeHwnd();
m_nDATA.uCallbackMessage = uMsgID;
m_nDATA.uFlags |= NIF_MESSAGE;
}
//
// 弹出菜单的实现函数
LRESULT CTrayIcon::OnTrayNotification(WPARAM wID, LPARAM lEvent)
{
if (wID != m_nDATA.uID ||(lEvent != WM_RBUTTONUP && lEvent != WM_LBUTTONDBLCLK)) return 0;
CMenu menu;
if (!menu.LoadMenu(m_nDATA.uID)) return 0;
CMenu* pSubMenu = menu.GetSubMenu(0);
if (!pSubMenu) return 0;
if (lEvent==WM_RBUTTONUP)
{
::SetMenuDefaultItem(pSubMenu-> m_hMenu, 0, TRUE);
CPoint ptMouse;
GetCursorPos(&ptMouse);
::SetForegroundWindow(m_nDATA.hWnd);
::TrackPopupMenu(pSubMenu-> m_hMenu, 0, ptMouse.x, ptMouse.y, 0, m_nDATA.hWnd, NULL);
}
else
{
::SendMessage(m_nDATA.hWnd, WM_COMMAND, pSubMenu-> GetMenuItemID(0), 0);
}
return 1;
}
//
// 决定是/否在托盘区显示图标,使之工作。
BOOL CTrayIcon::EnableTray(BOOL bShow)
{
UINT msg;
BOOL bResult = FALSE;
if(bShow)
{
if (NULL != m_icon)
{
msg = (NULL == m_nDATA.hIcon) ? NIM_ADD : NIM_MODIFY;
m_nDATA.hIcon = m_icon;
m_nDATA.uFlags |= NIF_ICON;
}
else
{
if (NULL == m_nDATA.hIcon) return FALSE;
msg = NIM_DELETE;
}
bResult = Shell_NotifyIcon(msg, &m_nDATA);
if (msg == NIM_DELETE || !bResult) m_nDATA.hIcon = NULL;
}
else
{
if (NULL != m_nDATA.hIcon)
{
msg = NIM_DELETE;
m_nDATA.hIcon = NULL;
bResult = Shell_NotifyIcon(msg, &m_nDATA);
}
}
return bResult;
}
#include "TrayIcon.h"
#include <afxpriv.h>
IMPLEMENT_DYNAMIC(CTrayIcon, CCmdTarget)
//
CTrayIcon::CTrayIcon()
{
memset(&m_nDATA, 0 , sizeof(m_nDATA));
m_nDATA.cbSize = sizeof(m_nDATA);
m_nDATA.uFlags = NIF_TIP|NIF_MESSAGE|NIF_ICON;
m_icon = NULL;
m_bShutdown = FALSE;
}
CTrayIcon::~CTrayIcon()
{
SetIcon((HICON)NULL);
EnableTray(FALSE);
m_icon = NULL;
}
//
// 初化化一个TrayIcon对象
void CTrayIcon::Create(CWnd* pNotifyWnd, //要关联的窗体
UINT uMsgID, //消息号
UINT uMenuID, //菜单资源编号
UINT uIcoID, //图标资源编号
UINT uTipID) //说明文本信号资源编号
{
ASSERT(::IsWindow(pNotifyWnd-> GetSafeHwnd()));
ASSERT(uMsgID > = WM_USER);
m_nDATA.hWnd = pNotifyWnd-> GetSafeHwnd();
m_nDATA.uCallbackMessage = uMsgID;
if(0 != uMenuID) SetMenu(uMenuID);
if(0 != uIcoID) SetIcon(uIcoID);
if(0 != uTipID) SetTipText(uTipID);
}
//
// 初化化一个TrayIcon对象
void CTrayIcon::Create(CWnd* pNotifyWnd, //要关联的窗体
UINT uMsgID, //消息号
UINT uMenuID, //菜单资源编号
UINT uIcoID, //图标资源编号
char* szTipText) //说明文本字串
{
ASSERT(::IsWindow(pNotifyWnd-> GetSafeHwnd()));
ASSERT(uMsgID > = WM_USER);
m_nDATA.hWnd = pNotifyWnd-> GetSafeHwnd();
m_nDATA.uCallbackMessage = uMsgID;
if(0 != uMenuID) SetMenu(uMenuID);
if(0 != uIcoID) SetIcon(uIcoID);
if(NULL != szTipText) SetTipText(szTipText);
}
//
// 根据资源ID,设置托盘区的图标
inline void CTrayIcon::SetIcon(UINT uID)
{
if(0 != uID)
{
m_icon = AfxGetApp()-> LoadIcon(uID);
m_nDATA.uFlags &= ~NIF_ICON;
if(NULL != m_icon) m_nDATA.uFlags |= NIF_ICON;
}
}
//
// 根据ICON名称,设置托盘区的图标
inline void CTrayIcon::SetIcon(LPCTSTR lpszIconName)
{
if((NULL != lpszIconName) && ( '\0 ' != lpszIconName[0]))
{
m_icon = ::LoadIcon(NULL, lpszIconName);
m_nDATA.uFlags &= ~NIF_ICON;
if(NULL != m_icon) m_nDATA.uFlags |= NIF_ICON;
}
}
//
// 根据ICON的句柄,设置托盘区的图标
inline void CTrayIcon::SetIcon(HICON hicon)
{
m_icon = hicon;
m_nDATA.uFlags &= ~NIF_ICON;
if(NULL != m_icon) m_nDATA.uFlags |= NIF_ICON;
}
//
// 根据工程的菜单的资源号,设置弹出菜单
inline void CTrayIcon::SetMenu(UINT uID)
{
m_nDATA.uID = uID;
}
//
// 根据资源号,设置提示文本
inline void CTrayIcon::SetTipText(UINT uID)
{
AfxLoadString(uID, m_nDATA.szTip, sizeof(m_nDATA.szTip));
m_nDATA.uFlags &= ~NIF_TIP;
if (m_nDATA.szTip[0] != '\0 ') m_nDATA.uFlags |= NIF_TIP;
}
//
// 设置提示文本
inline void CTrayIcon::SetTipText(LPCSTR lpTipText)
{
strncpy(m_nDATA.szTip, lpTipText, sizeof(m_nDATA.szTip));
m_nDATA.uFlags &= ~NIF_TIP;
if (m_nDATA.szTip[0] != '\0 ') m_nDATA.uFlags |= NIF_TIP;
}
//
// 设置关联窗体与消息号
void CTrayIcon::SetNotificationWnd(CWnd* pNotifyWnd, UINT uMsgID)
{
ASSERT(NULL != pNotifyWnd);
ASSERT(::IsWindow(pNotifyWnd-> GetSafeHwnd()));
ASSERT(uMsgID > = WM_USER);
m_nDATA.hWnd = pNotifyWnd-> GetSafeHwnd();
m_nDATA.uCallbackMessage = uMsgID;
m_nDATA.uFlags |= NIF_MESSAGE;
}
//
// 弹出菜单的实现函数
LRESULT CTrayIcon::OnTrayNotification(WPARAM wID, LPARAM lEvent)
{
if (wID != m_nDATA.uID ||(lEvent != WM_RBUTTONUP && lEvent != WM_LBUTTONDBLCLK)) return 0;
CMenu menu;
if (!menu.LoadMenu(m_nDATA.uID)) return 0;
CMenu* pSubMenu = menu.GetSubMenu(0);
if (!pSubMenu) return 0;
if (lEvent==WM_RBUTTONUP)
{
::SetMenuDefaultItem(pSubMenu-> m_hMenu, 0, TRUE);
CPoint ptMouse;
GetCursorPos(&ptMouse);
::SetForegroundWindow(m_nDATA.hWnd);
::TrackPopupMenu(pSubMenu-> m_hMenu, 0, ptMouse.x, ptMouse.y, 0, m_nDATA.hWnd, NULL);
}
else
{
::SendMessage(m_nDATA.hWnd, WM_COMMAND, pSubMenu-> GetMenuItemID(0), 0);
}
return 1;
}
//
// 决定是/否在托盘区显示图标,使之工作。
BOOL CTrayIcon::EnableTray(BOOL bShow)
{
UINT msg;
BOOL bResult = FALSE;
if(bShow)
{
if (NULL != m_icon)
{
msg = (NULL == m_nDATA.hIcon) ? NIM_ADD : NIM_MODIFY;
m_nDATA.hIcon = m_icon;
m_nDATA.uFlags |= NIF_ICON;
}
else
{
if (NULL == m_nDATA.hIcon) return FALSE;
msg = NIM_DELETE;
}
bResult = Shell_NotifyIcon(msg, &m_nDATA);
if (msg == NIM_DELETE || !bResult) m_nDATA.hIcon = NULL;
}
else
{
if (NULL != m_nDATA.hIcon)
{
msg = NIM_DELETE;
m_nDATA.hIcon = NULL;
bResult = Shell_NotifyIcon(msg, &m_nDATA);
}
}
return bResult;
}
//使用举例:
// MainFrm.h
#include "TrayIcon.h "
class CMainFrame : public CFrameWnd
{
protected:
DECLARE_DYNCREATE(CMainFrame)
protected:
CTrayIcon m_trayIcon;
protected:
//{{AFX_MSG(CMainFrame)
afx_msg LRESULT OnTrayNotification(WPARAM uID, LPARAM lEvent);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
#endif
// MainFrm.cpp
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE()
ON_COMMAND(ID_APP_SHUTDOWN, OnAppShutdown)
ON_COMMAND(ID_APP_OPEN, OnAppOpen)
ON_WM_CLOSE()
ON_MESSAGE(WM_TRAY_THEMSG, OnTrayNotification)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
//...
m_trayIcon.Create(this, WM_TRAY_THEMSG, IDR_MENUTRAY, IDR_DBTYPE);
//...
}
LRESULT CMainFrame::OnTrayNotification(WPARAM uID, LPARAM lEvent)
{
return m_trayIcon.OnTrayNotification(uID, lEvent);
}
void CMainFrame::OnAppShutdown()
{
m_trayIcon.m_bShutdown = TRUE;
SendMessage(WM_CLOSE);
}
void CMainFrame::OnAppOpen()
{
ShowWindow(SW_NORMAL);
SetForegroundWindow();
m_trayIcon.m_bShutdown = FALSE;
m_trayIcon.EnableTray(FALSE);
}
void CMainFrame::OnClose()
{
if (m_trayIcon.m_bShutdown)
CFrameWnd::OnClose();
else
{
ShowWindow(SW_HIDE);
m_trayIcon.m_bShutdown = TRUE;
m_trayIcon.EnableTray();
}
}
// MainFrm.h
#include "TrayIcon.h "
class CMainFrame : public CFrameWnd
{
protected:
DECLARE_DYNCREATE(CMainFrame)
protected:
CTrayIcon m_trayIcon;
protected:
//{{AFX_MSG(CMainFrame)
afx_msg LRESULT OnTrayNotification(WPARAM uID, LPARAM lEvent);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
#endif
// MainFrm.cpp
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE()
ON_COMMAND(ID_APP_SHUTDOWN, OnAppShutdown)
ON_COMMAND(ID_APP_OPEN, OnAppOpen)
ON_WM_CLOSE()
ON_MESSAGE(WM_TRAY_THEMSG, OnTrayNotification)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
//...
m_trayIcon.Create(this, WM_TRAY_THEMSG, IDR_MENUTRAY, IDR_DBTYPE);
//...
}
LRESULT CMainFrame::OnTrayNotification(WPARAM uID, LPARAM lEvent)
{
return m_trayIcon.OnTrayNotification(uID, lEvent);
}
void CMainFrame::OnAppShutdown()
{
m_trayIcon.m_bShutdown = TRUE;
SendMessage(WM_CLOSE);
}
void CMainFrame::OnAppOpen()
{
ShowWindow(SW_NORMAL);
SetForegroundWindow();
m_trayIcon.m_bShutdown = FALSE;
m_trayIcon.EnableTray(FALSE);
}
void CMainFrame::OnClose()
{
if (m_trayIcon.m_bShutdown)
CFrameWnd::OnClose();
else
{
ShowWindow(SW_HIDE);
m_trayIcon.m_bShutdown = TRUE;
m_trayIcon.EnableTray();
}
}