vc 更换命令栏图标

来源:互联网 发布:彩虹秒赞正版授权源码 编辑:程序博客网 时间:2024/05/21 12:44

 Shell_NotifyIcon

Windows 95/Windows NT任务栏的右边是一状态区,Windows95/Wi
ndowsNT在其上显示时间和一些小图标,这些图标代表着特定的功能或
程序,用鼠标单击、右击或双击这些图标,就会弹出功能菜单或程序
口等。你也许想把自己的
程序图标也放在任务栏的状态区上,很简单,
VC++ 5.0提供了一个函数,让你很容易地实现该功能。
Shell_NotifyIcon()函数
该函数发送消息给系统在任务栏的状态区,增加、删除或修改图
标。Shell_NotifyI con()有两个参数:
1. DWORD dwMessage
消息标志值,为以下三个中之一:
NIM_ADD
在任务栏状态区增加图标
NIM_DELETE 从任务栏状态区删除图标
NIM_MODITY 修改任务栏状态区的图标
2. PNOTIFYICONDATA pnid
指向NOTIFYICONDATA结构的指针。NOTIFYICONDATA结构如下:
typedef struct _NOTIFYICONDATA { // nid
DWORD cbSize; // NOTIFYICONDATA 结构的大小
HWND hWnd; //接收回调消息的窗口句柄
UINT uID; //自定义的图标标志值
UINT uFlags; //标志后面的三个数据成员哪个有效,
//可由NIF_ICON,NIF_MESSAGE和
  NIF_TIP组合。
UINT uCallbackMessage; //回调消息
HICON hIcon; //图标句柄
char szTip[64]; //提示字符。当把鼠标移到任务栏
//状态区该图标上时,系统显示该字符
} NOTIFYICONDATA, *PNOTIFYICONDATA;
如何在任务栏状态区实现
程序图标及其功能
1. 首先生成一个单
文档的工程文件。
2. 在StdAfx.h 添加自定义的消息:
//回调消息
#define MYWM_NOTIFYICON WM_USER+1
//在任务栏状态区显示图标的消息
#define MYWM_SHOWAPPICONIC WM_USER+2
3. 在MainFrm.h 里添加定义消息处理函数说明,该部分看起来如
下:
protected:
//{{AFX_MSG(CMainFrame)
afx_msg void OnSysCommand(UINT nID, LPARAM lParam); //手
工加
afx_msg void OnMyIconNotify(WPARAM wParam, LPARAM lParam
); //手工加
afx_msg void OnShowAppIconic(WPARAM wParam, LPARAM lPara
m); //手工加
afx_msg void OnClose(); //系统生成
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
另外,需在MainFrm.h定义一开关值,记录
程序窗口是打开或关闭
状态:
BOOL boolWndHadShow;
4. 在MainFrm.cpp里实现消息映射和消息处理函数。消息映射部
分看起来如下:
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
 //{{AFX_MSG_MAP(CMainFrame)
ON_MESSAGE(MYWM_NOTIFYICON, OnMyIconNotify)
 ON_MESSAGE(MYWM_SHOWAPPICONIC, OnShowAppIconic)
 ON_WM_SYSCOMMAND()
 ON_WM_CLOSE()
 //}}AFX_MSG_MAP
END_MESSAGE_MAP()
消息处理及相关函数如下所示:
//在任务栏状态区添加图标
BOOL MyTaskBarAddIcon(HWND hwnd, UINT uID, HICON hicon,
LPSTR lpszTip)
{
BOOL res;
NOTIFYICONDATA tnid;
tnid.cbSize = sizeof(NOTIFYICONDATA);
tnid.hWnd = hwnd;
tnid.uID = uID;
tnid.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE;
tnid.uCallbackMessage = MYWM_NOTIFYICON;
tnid.hIcon = hicon;
if (lpszTip)
lstrcpyn(tnid.szTip, lpszTip, sizeof(tnid.szTip));
else
tnid.szTip[0]=‘/0';
res=shell_NotifyIco n(NIM_ADD, &tnid);
if (hicon)
DestroyIcon(hicon);
return res;
}
//从任务栏状态区删除图标
BOOL MyTaskBarDeleteIcon(HWND hwnd, UINT uID)
{
BOOL res;
NOTIFYICONDATA tnid;
tnid.cbSize = sizeof(NOTIFYICONDATA);
tnid.hWnd = hwnd;
tnid.uID = uID;
res = Shell_NotifyIcon(NIM_DELETE, &tnid);
return res;
}
//处理图标回调消息MYWM_NOTIFYICON
void CMainFrame::OnMyIconNotify( WPARAM wParam, LPARAM l
Param )
{
UINT nID;
UINT uMouseMsg;
nID = (UINT)wParam;
uMouseMsg = (UINT) lParam;
if(uMouseMsg == WM_LBUTTONDOWN)
 //点击图标
{
if( boolWndHadShow ) //如果窗口已打开,隐藏窗口
ShowWindow(SW_HIDE );
else
 //否则,显示窗口
ShowWindow(SW_SHOWNORMAL );
boolWndHadShow = ~boolWndHadShow;
}
}
//消息MYWM_SHOWAPPICONIC处理函数,在任务栏显示图标并隐藏
窗口
void CMainFrame::OnShowAppIconic(WPARAM wParam, LPARAM l
Param )
{
HICON theIcon = LoadIcon(AfxGetInstance-Handle(),MAKEINT
RESOURCE(IDR_MAI NFRAME) );
MyTaskBarAddIcon(GetSafeHwnd(), 100, theIcon, _T("示范程
序"));
ShowWindow(SW_HIDE );
boolWndHadShow = FALSE;
}
程序关闭时,需把图标从任务样状态区删除,你可以添加一个处
理WM_CLOSE消息的函数来删除图标。通过ClassWizard来添加处理WM_
CLOSE的函数OnClose(),该函数如下:
void CMainFrame::OnClose()
{
// TODO: Add your message handler code here and/or call
default
MyTaskBarDeleteIcon( GetSafeHwnd(), 100 );
CFrameWnd::OnClose();
}
当用户把窗口最小化时,你应隐藏整个窗口,所以要处理ON_SYSCO
MMAND消息。首先在MainFrm.h添加函数说明,如第三步所示;然后在Ma
inFrm.cpp里说明消息映射和实现函数。消息映射如前面所示,函数实
现如下:
void CMainFrame::OnSysCommand(UINT nID, LPARAM lParam )
{
if (nID==SC_MINIMIZE )
{
ShowWindow(SW_HIDE );
boolWndHadShow=FALSE;
}
else
CWnd::OnSysCommand(nID, lParam );
}
5. 在InitInstance()函数返回前,添加一语句
m_pMainWnd->PostMessage( MYWM_SHOWAP- PICONIC );
它是发送一个自定义的消息MYWM_SHOWAP- PICONIC使
程序启动后
隐藏
程序窗口并在任务栏状态区显示小图标。
6. 现在,你可编译和运行该
程序了。程序运行后,点击任务栏状
态区该
程序的图标, 系统会弹出程序窗口,再点击一下,又隐藏了。

VC++任务栏图标的实现
2008-12-26 15:05

目前,许多应用软件都实现了WINDOW任务栏提示区图标,如金山词霸、超级解霸
等,这不仅增强了软件的特色,更方便了用户的使用。本文将介绍一个封装好的
类,用VC++来实现这项功能,希望对读者有所帮助。
一、一个简单的直接引用的方法:
我们可以使用直接引用WIN32 API函数的方法实现任务栏提示区图标。
1、定义一个NOTIFYICONDATA数据结构,初始化各数据项。其结构详见在线帮助。
2、使用WIN32 API函数Shell_NotifyIcon实现任务栏提示区图标。函数原形如下:
WINSHELLAPI BOOL WINAPI Shell_NotifyIcon(DWORD dwMessage,//消息类型
PNOTIFYICONDATA pnid //指向NOTIFYICONDATA结构的指针
);
消息类型包括:NIM_ADD 增加图标到任务栏;
NIM_DELETE 从任务栏删除图标;
NIM_MODIFY 修改任务栏图标;
二、一个更好的面对对象的方法:
为了使使用更加方便、合理,更符合面对对象的处理方法,我们应当封装一个类
(CSystemIcon),由此类实现任务栏提示区图标。
1、由CObject类派生出CsystemIcon类。
2、构造下列函数:
LRESULT OnIconNotification(WPARAM wID,LPARAM lEvent) //自定义消息处理函数
void DeleteIcon() //删除图标
void HideIcon() //隐藏图标
void ShowIcon() //显示图标
BOOL SetTooltipText(LPCTSTR pszTip) //设置提示文本
BOOL SetTooltipText(UINT nID)
CString GetTooltipText() const //得到提示文本
BOOL SetNotificationWnd(CWnd* pWnd) //设置通知窗口
CWnd* GetNotificationWnd() const //得到通知窗口
HICON GetIcon() const //得到图标
BOOL SetIcon(HICON hIcon) //设置图标
BOOL SetIcon(LPCTSTR lpszIconName)
BOOL SetIcon(UINT nIDResource)
BOOL SetStandardIcon(LPCTSTR lpIconName) //设置系统标准图标
BOOL SetStandardIcon(UINT nIDResource)
3、生成的CsystemIcon类详见下列源文件:
a、CsystemIcon类.H头文件:
/////////////////////////////////////////////////////////////////////////////
// SystemIcon.h : header file
//
#ifndef _INCLUDED_SYSTEMICON_H_
#define _INCLUDED_SYSTEMICON_H_
/////////////////////////////////////////////////////////////////////////////
// CSystemIcon window
class CSystemIcon : public CObject
// Construction/destruction
public:
CSystemIcon();
CSystemIcon(CWnd* pWnd, UINT uCallbackMessage, LPCTSTR szTip, HICON icon, UINT uID);
virtual ~CSystemIcon();
// Operations
public:
BOOL Enabled() { return m_bEnabled; }
BOOL Visible() { return !m_bHidden; }
//创建系统图标
Create(CWnd* pWnd, UINT uCallbackMessage, LPCTSTR szTip, HICON icon, UINT uID);
//关于提示文本
BOOL SetTooltipText(LPCTSTR pszTooltipText);
BOOL SetTooltipText(UINT nID);
CString GetTooltipText() const;
//关于图标
BOOL SetIcon(HICON hIcon);
BOOL SetIcon(LPCTSTR lpIconName);
BOOL SetIcon(UINT nIDResource);
BOOL SetStandardIcon(LPCTSTR lpIconName);
BOOL SetStandardIcon(UINT nIDResource);
HICON GetIcon() const;
void HideIcon();
void ShowIcon();
void DeleteIcon();
//关于通知窗口
BOOL SetNotificationWnd(CWnd* pNotifyWnd);
CWnd* GetNotificationWnd() const;
//自定义消息处理函数
virtual LRESULT OnIconNotification(WPARAM uID, LPARAM lEvent);
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CSystemIcon)
//}}AFX_VIRTUAL
// Implementation
protected:
BOOL m_bEnabled; //是否支持图标
BOOL m_bHidden; //是否隐藏图标
NOTIFYICONDATA m_tnd; //数据结构,请参考在线帮助
DECLARE_DYNAMIC(CSystemIcon)
};
#endif
/////////////////////////////////////////////////////////////////////////////
b、CsystemIcon类.CPP源文件:
/////////////////////////////////////////////////////////////////////////////
// SystemIcon.cpp : implementation file
#include "stdafx.h"
#include "SystemIcon.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNAMIC(CSystemIcon, CObject)
/////////////////////////////////////////////////////////////////////////////
CSystemIcon::CSystemIcon()
memset(&m_tnd, 0, sizeof(m_tnd));
m_bEnabled = FALSE;
m_bHidden = FALSE;
CSystemIcon::CSystemIcon(CWnd* pWnd, UINT uCallbackMessage, LPCTSTR szToolTip,
HICON icon, UINT uID)
Create(pWnd, uCallbackMessage, szToolTip, icon, uID);
m_bHidden = FALSE;
BOOL CSystemIcon::Create(CWnd* pWnd, UINT uCallbackMessage, LPCTSTR szToolTip,
HICON icon, UINT uID)
//文件只能使用在WINDOW 95以上的版本中
VERIFY(m_bEnabled = ( GetVersion() & 0xff ) >= 4);
if (!m_bEnabled) return FALSE;
//确认通知窗口有效
VERIFY(m_bEnabled = (pWnd && ::IsWindow(pWnd->GetSafeHwnd())));
if (!m_bEnabled) return FALSE;
//确认自定义消息大于WM_USER
ASSERT(uCallbackMessage >= WM_USER);
//确定提示文本长度小于64
ASSERT(_tcslen(szToolTip) <= 64);
//定义NOTIFYICONDATA结构的数据项
m_tnd.cbSize = sizeof(NOTIFYICONDATA);
m_tnd.hWnd = pWnd->GetSafeHwnd();
m_tnd.uID = uID;
m_tnd.hIcon = icon;
m_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
m_tnd.uCallbackMessage = uCallbackMessage;
strcpy (m_tnd.szTip, szToolTip);
//设置图标
VERIFY(m_bEnabled = Shell_NotifyIcon(NIM_ADD, &m_tnd));
return m_bEnabled;
CSystemIcon::~CSystemIcon()
DeleteIcon();
/////////////////////////////////////////////////////////////////////////////
void CSystemIcon::DeleteIcon()
if (!m_bEnabled) return;
m_tnd.uFlags = 0;
Shell_NotifyIcon(NIM_DELETE, &m_tnd);
m_bEnabled = FALSE;
void CSystemIcon::HideIcon()
if (m_bEnabled && !m_bHidden) {
m_tnd.uFlags = NIF_ICON;
Shell_NotifyIcon (NIM_DELETE, &m_tnd);
m_bHidden = TRUE;
void CSystemIcon::ShowIcon()
if (m_bEnabled && m_bHidden) {
m_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
Shell_NotifyIcon(NIM_ADD, &m_tnd);
m_bHidden = FALSE;
BOOL CSystemIcon::SetIcon(HICON hIcon)
if (!m_bEnabled) return FALSE;
m_tnd.uFlags = NIF_ICON;
m_tnd.hIcon = hIcon;
return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);
BOOL CSystemIcon::SetIcon(LPCTSTR lpszIconName)
HICON hIcon = AfxGetApp()->LoadIcon(lpszIconName);
return SetIcon(hIcon);
BOOL CSystemIcon::SetIcon(UINT nIDResource)
HICON hIcon = AfxGetApp()->LoadIcon(nIDResource);
return SetIcon(hIcon);
BOOL CSystemIcon::SetStandardIcon(LPCTSTR lpIconName)
HICON hIcon = LoadIcon(NULL, lpIconName);
return SetIcon(hIcon);
BOOL CSystemIcon::SetStandardIcon(UINT nIDResource)
HICON hIcon = LoadIcon(NULL, MAKEINTRESOURCE(nIDResource));
return SetIcon(hIcon);
HICON CSystemIcon::GetIcon() const
HICON hIcon = NULL;
if (m_bEnabled)
hIcon = m_tnd.hIcon;
return hIcon;
BOOL CSystemIcon::SetTooltipText(LPCTSTR pszTip)
if (!m_bEnabled) return FALSE;
m_tnd.uFlags = NIF_TIP;
_tcscpy(m_tnd.szTip, pszTip);
return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);
BOOL CSystemIcon::SetTooltipText(UINT nID)
CString strText;
VERIFY(strText.LoadString(nID));
return SetTooltipText(strText);
CString CSystemIcon::GetTooltipText() const
CString strText;
if (m_bEnabled)
strText = m_tnd.szTip;
return strText;
BOOL CSystemIcon::SetNotificationWnd(CWnd* pWnd)
if (!m_bEnabled) return FALSE;
ASSERT(pWnd && ::IsWindow(pWnd->GetSafeHwnd()));
m_tnd.hWnd = pWnd->GetSafeHwnd();
m_tnd.uFlags = 0;
return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);
CWnd* CSystemIcon::GetNotificationWnd() const
return CWnd::FromHandle(m_tnd.hWnd);
LRESULT CSystemIcon::OnIconNotification(UINT wParam, LONG lParam)
if (wParam != m_tnd.uID)
return 0L;
CMenu menu, *pSubMenu;
//单击右键弹出菜单
if (LOWORD(lParam) == WM_RBUTTONUP)
if (!menu.LoadMenu(m_tnd.uID)) return 0;
if (!(pSubMenu = menu.GetSubMenu(0))) return 0;
//设定第一项为缺省
::SetMenuDefaultItem(pSubMenu->m_hMenu, 0, TRUE);
//定义弹出菜单
CPoint pos;
GetCursorPos(&pos);
::SetForegroundWindow(m_tnd.hWnd);
::TrackPopupMenu(pSubMenu->m_hMenu, 0, pos.x, pos.y, 0, m_tnd.hWnd, NULL);
::PostMessage(m_tnd.hWnd, WM_NULL, 0, 0);
menu.DestroyMenu();
else if (LOWORD(lParam) == WM_LBUTTONDBLCLK)
if (!menu.LoadMenu(m_tnd.uID)) return 0;
if (!(pSubMenu = menu.GetSubMenu(0))) return 0;
//双击左键起动缺省菜单
::SetForegroundWindow(m_tnd.hWnd);
::SendMessage(m_tnd.hWnd, WM_COMMAND, pSubMenu->GetMenuItemID(0), 0);
menu.DestroyMenu();
return 1;
三、一个简单的例子
1、使用MFC AppWizard(EXE)创建项目文件。
2、用Add to Project添加CSystemIcon类的.h文件与.CPP文件到工程中。
3、在CFrameWnd类中添加下列语句:
//自定义消息
#define WM_ICON_NOTIFY WM_USER+10
//定义成员变量
#include "SystemIcon.h"
CSystemIcon m_systemIcon
4、定义消息映象与消息处理函数
a、BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
...
ON_MESSAGE(WM_ICON_NOTIFY, OnIconNotification)
END_MESSAGE_MAP()
b、LRESULT CMainFrame::OnIconNotification(WPARAM wParam, LPARAM lParam)
return m_systemIcon.OnIconNotification(wParam, lParam);
c、定义LRESULT OnIconNotification(WPARAM wParam, LPARAM lParam);
5、创建系统图标(在OnCreate中加添加):
HICON hIcon=AfxGetApp()->LoadIcon(IDI_MAINFRAME);
if (!m_systemIcon.Create(this, //消息通知窗口
WM_ICON_NOTIFY,//自定义消息
"MY SAMPLE", //提示字符串
hIcon, //图标ID号
IDR_POPUP_MENU //弹出菜单ID号
))
return -1;
6、打开资源,创建弹出菜单(IDR_POPUP_MENU),CAPTION为(_POPUP_):
菜单项包括:a、关于(ID_APP_ABOUT) b、例子(ID_APP_APP) c、退出(ID_APP_EXIT)
用ClassWizard定义(ID_APP_APP)消息处理函数,添加:AfxGetMainWnd()->ShowWindow(SW_SHOW);
7、打开资源,创建图标(IDI_ICON1)。
8、删除应用类中的函数InitInstance中的pMainFrame->ShowWindow(m_nCmdShow)语句。
9、编译执行形成执行文件。

 

 

 

                                 任务栏显示图标

NIF_MESSAGE;tnid.uCallbackMessage = MYWM_NOTIFYICON;tnid.hIcon = hicon;if (lpszTip) lstrcpyn(tnid.szTip, lpszTip, sizeof(tnid.szTip));else tnid.szTip[0]=‘/0‘;res=shell_NotifyIco n(NIM_ADD, tnid);if (hicon)DestroyIcon(hicon);return res;}//从任务栏状态区删除图标BOOL MyTaskBarDeleteIcon(HWND hwnd, UINT uID){BOOL res;NOTIFYICONDATA tnid;tnid.cbSize = sizeof(NOTIFYICONDATA);tnid.hWnd = hwnd;tnid.uID = uID;res = Shell_NotifyIcon(NIM_DELETE, tnid);return res;}//处理图标回调消息MYWM_NOTIFYICONvoid CMainFrame::OnMyIconNotify( WPARAM wParam, LPARAM lParam ){UINT nID;UINT uMouseMsg;nID = (UINT)wParam;uMouseMsg = (UINT) lParam;if(uMouseMsg == WM_LBUTTONDOWN)//图标{if( boolWndHadShow ) //如果窗口已打开,隐藏窗口 ShowWindow(SW_HIDE );else//否则,显示窗口 ShowWindow(SW_SHOWNORMAL );boolWndHadShow = ~boolWndHadShow;}}//消息MYWM_SHOWAPPICONIC处理函数,在任务栏显示图标并隐藏窗口void CMainFrame::OnShowAppIconic(WPARAM wParam, LPARAM lParam ){HICON theIcon = LoadIcon(AfxGetInstance-Handle(),MAKEINTRESOURCE(IDR_MAI NFRAME) );MyTaskBarAddIcon(GetSafeHwnd(), 100, theIcon, _T("示范程序"));ShowWindow(SW_HIDE );boolWndHadShow = FALSE;}当程序关闭时,需把图标从任务样状态区删除,你可以添加一个处理WM_CLOSE消息的函数来删除图标。通过ClassWizard来添加处理WM_CLOSE的函数OnClose(),该函数如下:void CMainFrame::OnClose(){ // TODO: Add your message handler code here and/or call default MyTaskBarDeleteIcon( GetSafeHwnd(), 100 ); CFrameWnd::OnClose();}当用户把窗口最小化时,你应隐藏整个窗口,所以要处理ON_SYSCOMMAND消息。首先在MainFrm.h添加函数说明,如第三步所示;然后在MainFrm.cpp里说明消息映射和实现函数。消息映射如前面所示,函数实现如下:void CMainFrame::OnSysCommand(UINT nID, LPARAM lParam ){if (nID==SC_MINIMIZE ){ ShowWindow(SW_HIDE ); boolWndHadShow=FALSE;}else CWnd::OnSysCommand(nID, lParam );}5. 在InitInstance()函数返回前,添加一语句m_pMainWnd-PostMessage( MYWM_SHOWAP- PICONIC );它是发送一个自定义的消息MYWM_SHOWAP- PICONIC使程序启动后隐藏程序窗口并在任务栏状态区显示小图标。6. 现在,你可编译和运行该程序了。程序运行后,任务栏状态区该程序的图标, 系统会弹出程序窗口,再一下,又隐藏了。

 

原创粉丝点击