VC++托盘图标实现类封装及使用(附源码)

Posted dvlinker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VC++托盘图标实现类封装及使用(附源码)相关的知识,希望对你有一定的参考价值。

       在系统桌面右下角的托盘区域,创建一个托盘图标,已经是很多软件的标配了,特别是IM即时通讯软件,要在托盘图标上显示来消息时的闪动头像。

       其实托盘图标创建很简单,使用起来也比较方便,主要是调用Shell_NotifyIcon API函数,传入不同参数表示对应的操作:

1)NIM_ADD:创建一个托盘图标;

2)NIM_MODIFY:修改托盘图标,主要是用来修改图标和提示文字的;

3)NIM_DELETE:删除托盘图标。

下面给出一个完整的托盘图标封装类。

1、托盘图标封装类CTrayIcon

       主要有CTrayIcon::CreateCTrayIcon::SetIconCTrayIcon::SetTooltipTextCTrayIcon::OnIconNotification等几个接口。其中,CTrayIcon::Create接口用来创建托盘图标;CTrayIcon::SetIcon用来设置图标或者修改图标;CTrayIcon::SetTooltipText用来设置托盘图标的提示文字;CTrayIcon::OnIconNotification用来处理托盘图标的鼠标消息。

         CTrayIcon类的头文件如下

#ifndef TRAYICON_H
#define TRAYICON_H

class CTrayIcon

private:
	CTrayIcon(); 
	CTrayIcon( CWnd* pWnd, WORD uCallbackMessage, LPCTSTR szTip, HICON icon, WORD uID ); 

public: 
	~CTrayIcon(); 
	static CTrayIcon& Instance();

public: 
	// 创建系统图标 
	BOOL Create( CWnd* pWnd, WORD uCallbackMessage, LPCTSTR szTip, HICON icon, WORD uID );

	// 获取NOTIFYICONDATA信息
	NOTIFYICONDATA GetNotifyIconData() return m_tnd; 

	// 关于提示文本 
	BOOL32 SetTooltipText( LPCTSTR pszTooltipText ); 
	BOOL32 SetTooltipText( WORD nID ); 
	CString GetTooltipText() const; 

	// 关于图标 
	BOOL32 SetIcon( HICON hIcon ); 
	BOOL32 SetIcon( LPCTSTR lpIconName ); 
	BOOL32 SetIcon( WORD nIDResource ); 
	HICON GetIcon() const; 
	void HideIcon(); 
	void ShowIcon(); 
	void DeleteIcon(); 

	// 关于通知窗口 
	BOOL32 SetNotificationWnd( CWnd* pNotifyWnd ); 
	CWnd* GetNotificationWnd() const; 

	CPoint GetTrayCursorPos();

	// 自定义消息处理函数 
	virtual LRESULT OnIconNotification( WPARAM wParam, LPARAM lParam ); 

protected: 
	NOTIFYICONDATA m_tnd;       // 数据结构,请参考在线帮助 
	CPoint m_trayCursorPos;     // 托盘响应WM_MOUSEMOVE时的鼠标坐标
	BOOL32 m_bProcessingBtnMsg; // 是否在处理右键单击或左键双击托盘消息,此时应将消息盒子提示窗口掩藏掉
;

#endif

       CTrayIcon类的cpp源文件如下

#include "stdafx.h"
#include "trayicon.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


CTrayIcon::CTrayIcon()   
: m_trayCursorPos( CPoint(0, 0) ) 
, m_bProcessingBtnMsg( FALSE ) 
 
	memset( &m_tnd, 0, sizeof(m_tnd) ); 
 

CTrayIcon::CTrayIcon( CWnd* pWnd, WORD uCallbackMessage, LPCTSTR szToolTip, HICON icon, WORD uID ) 
 
	Create( pWnd, uCallbackMessage, szToolTip, icon, uID );  
 

CTrayIcon& CTrayIcon::Instance()

	static CTrayIcon s_hInstance;
	return s_hInstance;


CTrayIcon::~CTrayIcon()

	HideIcon();
	DeleteIcon();


BOOL32 CTrayIcon::Create( CWnd* pWnd, WORD uCallbackMessage, LPCTSTR szToolTip, HICON icon, WORD uID ) 
 
	BOOL32 bEnabled = FALSE;

	// 文件只能使用在WINDOW 95以上的版本中 
	VERIFY( bEnabled = ( GetVersion() & 0xff ) >= 4 ); 
	if ( !bEnabled ) 
	
		uilog( _T("[CTrayIcon::Create] os version below WINDOW 95") );
		return FALSE; 
	

	// 确认通知窗口有效 
	VERIFY( bEnabled = (pWnd && ::IsWindow(pWnd->GetSafeHwnd())) ); 
	if ( !bEnabled ) 
	
		uilog( _T("[CTrayIcon::Create] handle of main window is invalid") );
		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 ); 

	// 设置图标 
	bEnabled = Shell_NotifyIcon( NIM_ADD, &m_tnd ); 
	if ( !bEnabled )
	
		uilog( _T("[CTrayIcon::Create] Shell_NotifyIcon[NIM_ADD] failed") );
	

	return bEnabled; 
 

void CTrayIcon::DeleteIcon() 
 
	m_tnd.uFlags = 0; 
	Shell_NotifyIcon( NIM_DELETE, &m_tnd ); 
 

void CTrayIcon::HideIcon() 
  
	m_tnd.uFlags = NIF_ICON; 
	Shell_NotifyIcon( NIM_DELETE, &m_tnd ); 
 

void CTrayIcon::ShowIcon() 
 
	m_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; 
	Shell_NotifyIcon( NIM_ADD, &m_tnd ); 
 

BOOL32 CTrayIcon::SetIcon( HICON hIcon ) 
 
	if ( hIcon == NULL )
	
		WriteTrayIconLog( _T("[CTrayIcon::SetIcon(HICON hIcon)]hIcon == NULL"));
	
	else
	
		WriteTrayIconLog( _T("[CTrayIcon::SetIcon(HICON hIcon)]hIcon = %d"), hIcon );
	

	m_tnd.uFlags = NIF_ICON; 
	m_tnd.hIcon = hIcon; 
	BOOL32 bRet = Shell_NotifyIcon( NIM_MODIFY, &m_tnd ); 
	if ( !bRet )
	
		WriteTrayIconLog( _T("[CTrayIcon::SetIcon(HICON hIcon)]Shell_NotifyIcon(NIM_MODIFY-NIF_ICON) failed, lasterrid: %d"), GetLastError() );
	

	return bRet;
 

BOOL32 CTrayIcon::SetIcon( LPCTSTR lpszIconName ) 
 
	WriteTrayIconLog( _T("[CTrayIcon::SetIcon(LPCTSTR lpszIconName)]lpszIconName = %s"), lpszIconName );

	HICON hIcon = AfxGetApp()->LoadIcon( lpszIconName ); 
	return SetIcon( hIcon ); 
 

BOOL32 CTrayIcon::SetIcon( WORD nIDResource ) 
 
	WriteTrayIconLog( _T("[CTrayIcon::SetIcon(WORD nIDResource)]nIDResource = %d"), nIDResource );

	HICON hIcon = AfxGetApp()->LoadIcon( nIDResource ); 
	return SetIcon( hIcon ); 
 

HICON CTrayIcon::GetIcon() const 
 
	HICON hIcon = NULL; 

	hIcon = m_tnd.hIcon;

	return hIcon; 
 

BOOL32 CTrayIcon::SetTooltipText( LPCTSTR pszTip ) 
 
	m_tnd.uFlags = NIF_TIP; 
	_tcscpy( m_tnd.szTip, pszTip ); 

	return Shell_NotifyIcon( NIM_MODIFY, &m_tnd ); 
 

BOOL32 CTrayIcon::SetTooltipText( WORD nID ) 
 
	CString strText; 
	VERIFY( strText.LoadString( nID ) ); 

	return SetTooltipText( strText ); 
 

CString CTrayIcon::GetTooltipText() const 
 
	CString strText; 

	strText = m_tnd.szTip; 

	return strText; 
 

BOOL32 CTrayIcon::SetNotificationWnd( CWnd* pWnd ) 
 
	ASSERT( pWnd && ::IsWindow( pWnd->GetSafeHwnd() ) ); 
	m_tnd.hWnd = pWnd->GetSafeHwnd(); 
	m_tnd.uFlags = 0; 

	return Shell_NotifyIcon( NIM_MODIFY, &m_tnd ); 
 

CWnd* CTrayIcon::GetNotificationWnd() const 
 
	return CWnd::FromHandle( m_tnd.hWnd ); 
 

LRESULT CTrayIcon::OnIconNotification( WPARAM wParam, LPARAM lParam ) 
 
	if ( WM_MOUSEMOVE == lParam )
	
        // 鼠标移动消息

		return 0;
	

	if ( wParam != m_tnd.uID ) 
	
		return 0L; 
	

	// 单击右键弹出菜单 
	if ( WM_RBUTTONUP == LOWORD(lParam) ) 
	 	
        // 右键弹起消息处理
	 
	else if ( WM_LBUTTONDOWN == LOWORD(lParam) || WM_LBUTTONDBLCLK == LOWORD(lParam) ) 
	 
		// 单击或者双击消息处理
		

		m_bProcessingBtnMsg = FALSE;
	

	return 1; 
 

CPoint CTrayIcon::GetTrayCursorPos()

	return m_trayCursorPos;

2、调用CTrayIcon::Create创建图标

        调用CTrayIcon::Create接口创建图标,创建时第一个参数是接收托盘通知消息的窗口,第二个参数是托盘被操作时回调的窗口自定义消息id,后面几个参数是用来设置托盘图标的提示文字和图标icon的,相关代码如下:

// 利用图标资源的ID去创建托盘图标
BOOL32 CreateTrayIcon( WORD nIDResource )

	BOOL32 bSuccess = FALSE;
	HICON hIcon = LoadIcon( AfxGetResourceHandle(), MAKEINTRESOURCE( nIDResource ) );
	bSuccess = CTrayIcon::Instance().Create( this, WM_MY_TRAY_NOTIFICATION, _T("托盘图标提示文字"), hIcon, IDI_ICON_SYSTEM );

	CTrayIcon::Instance().SetIcon( hIcon );
	CTrayIcon::Instance().ShowIcon();

	return bSuccess;

3、将回调给指定窗口的托盘图标操作自定义消息投递到CTrayIcon::OnIconNotification接口中去处理

      从创建托盘图标的代码可以看出,回调给指定窗口的托盘图标操作消息是自定义消息,是用户在创建托盘图标时指定的。先添加自定义消息的映射,接收到自定义消息,然后投递到CTrayIcon::OnIconNotification接口中去处理。相关代码如下:

LRESULT OnTrayNotification( WPARAM wParam, LPARAM lParam )
ON_MESSAGE( WM_MY_TRAY_NOTIFICATION, OnTrayNotification )
LRESULT CMainFrameWnd::OnTrayNotification( WPARAM wParam, LPARAM lParam )

	return CTrayIcon::Instance().OnIconNotification( wParam, lParam );

以上是关于VC++托盘图标实现类封装及使用(附源码)的主要内容,如果未能解决你的问题,请参考以下文章

VC++使用zlib压缩及解压数据,使用base64编码及解码数据(附源码)

实现动态系统托盘图标

VC++解决Windows快捷方式图标不刷新问题(附源码)

动态系统托盘图标

VC++实现打开文件和打开所在文件夹的功能(附源码)

Qt系统托盘