托盘在任务栏的右下角,下图就是一个托盘(抓那个图标就是之后的文章要介绍的抓图程序,不要BS我的审美),英文名字很酷--Tray
这是个看起来很诱人的功能。
我们只需要了解:
一个结构NOTIFYICONDATA
一个API Shell_NotifyIcon
就可以实现它,知道这个API后你就可以去msdn查查怎么用,当然如果你很懒得话就用我将要列出来的这个类吧,很容易使用。
class CTrayIcon // 添加托盘图标到系统托盘类
... {
public:
CTrayIcon(void);
~CTrayIcon(void);
public:
void Init( HWND hWnd ,DWORD uID ,UINT nMsg ,const TCHAR * msg ); //初始化托盘图标
void ShowIcon( ); //添加托盘图标到系统托盘
BOOL ShowBalloon( LPCTSTR InfoTitle , LPCTSTR Info , UINT InfoType );
void DeleteIcon( ); //删除托盘图标
private:
NOTIFYICONDATA m_TrayIcon; //托盘图标类型的变量
} ;
/**/ /*
* All rights reserved.
* Li Xin
* 文件名称:TrayIcon.cpp
* 文件标识:
* 摘 要:实现托盘图标
*/
#include " StdAfx.h "
#include " TrayIcon.h "
/**/ /*******************************************************************************
* 函数名:CTrayIcon
* 功 能:添加托盘图标类的构造函数
* 返回值:无
* 参数列表:无
********************************************************************************/
CTrayIcon::CTrayIcon( void )
... {
}
/**/ /********************************************************************************
* 函数名:CTrayIcon
* 功 能:添加托盘图标类的析构函数
* 返回值:无
* 参数列表:无
********************************************************************************/
CTrayIcon:: ~ CTrayIcon( void )
... {
}
/**/ /*******************************************************************************
* 函数名:Init
* 功 能:初始化托盘图标
* 返回值:void
* 参数列表:)hWnd 类型:HWND 说明:主窗口句柄
* 2)uID 类型:DWORD 说明:托盘图标id
3)nMsg 类型:UINT 说明:Tray的事件会通过此消息通知应用程序
4)str 类型:TCHAR 说明:鼠标放在图标上后显示的文本信息
*******************************************************************************/
void CTrayIcon::Init( HWND hWnd ,DWORD uID ,UINT nMsg , const TCHAR * msg )
... {
m_TrayIcon.cbSize = sizeof( NOTIFYICONDATA ); //结构所占的字节数,必须用结构的大小来初始化
m_TrayIcon.hWnd = hWnd; //接受Tray图标消息的窗口句柄
m_TrayIcon.uID = uID; //由应用程序定义的图标ID
m_TrayIcon.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP; //用来鉴别那些需要改变其值的域,NIF_ICON表示hIcon有效,可用来修改图标,NIF_MESSAGE表示uCallbackMessage有效,用来定义消息,NIF―TIP表示szTip参数有效,可修改工具提示。
m_TrayIcon.uCallbackMessage = nMsg; // 应用程序定义的消息
m_TrayIcon.hIcon = AfxGetApp( )->LoadIcon( uID ); //Tray图标的句柄
lstrcpy( m_TrayIcon.szTip ,msg ); //szTip[64]为工具提示的文本
}
/**/ /******************************************************************************
* 函数名:ShowIcon
* 功 能:添加托盘图标到系统托盘
* 返回值:void
* 参数列表:无
*******************************************************************************/
void CTrayIcon::ShowIcon( )
... {
Shell_NotifyIcon(NIM_ADD,&m_TrayIcon); //添加最小化图标
}
/**/ /******************************************************************************
* 函数名:DeleteIcon
* 功 能:删除托盘图标
* 返回值:void
* 参数列表:无
*******************************************************************************/
void CTrayIcon::DeleteIcon( )
... {
Shell_NotifyIcon( NIM_DELETE,&m_TrayIcon ); //删除最小化图标
}
/**/ /******************************************************************************
* 函数名:ShowBalloon
* 功 能:显示气球对话框
* 返回值:void
* 参数列表:)InfoTitle 类型:LPCTSTR 说明:信息标题
2)Info 类型:LPCTSTR 说明:信息内容
3)InfoType 类型:UINT 说明:信息类型
*******************************************************************************/
BOOL CTrayIcon::ShowBalloon( LPCTSTR InfoTitle , LPCTSTR Info , UINT InfoType )
... {
m_TrayIcon.uFlags = NIF_INFO;
m_TrayIcon.uTimeout = 1500;
m_TrayIcon.dwInfoFlags = NIIF_INFO;
lstrcpy ( m_TrayIcon.szInfo, Info );
lstrcpy ( m_TrayIcon.szInfoTitle, InfoTitle );
return Shell_NotifyIcon(NIM_MODIFY, &m_TrayIcon);
}
使用起来很容易:
定义一个自定义消息
#define WM_TRAYPROC WM_USER+123
CTrayIcon tray;声明一个全局变量
在你主对话框的OnInitDialog中添加
tray.Init(m_hWnd, IDI_TRAY, WM_TRAYPROC, L"按Esc退出抓图");
tray.ShowIcon();
tray.ShowBalloon(L"Notify", L"按Ctrl + Shit + M 键截图/r截图模式:/rEsc取消截图/r回车复制进剪切板", NIF_INFO);
在OnClose中调用
tray.DeleteIcon();
其中ShowBalloon是显示一个气球,传说中XP下有个Bug,这个气球本来能够定时显示多长时间后自动关闭,但是XP下这个功能不好使。
Okay! 我们平时所看到的托盘都能够相应操作,这个是如何实现的呢?刚刚定义了一个WM_TRAYPROC消息,就是做这个事情的。
需要在对话框中处理消息循环,参考下面的代码可以处理消息。
这是个基本的封装,你可以根据msdn的信息来扩展它。
Okay, that’s all!想为你的程序加上托盘功能么?Try it! Enjoy it!
... {
if (message == WM_TRAYPROC)
...{
UINT uMouseMsg; //鼠标动作
uMouseMsg = (UINT) lParam;
if (uMouseMsg == WM_LBUTTONDOWN) //鼠标左键响应
...{
//if (!IsWindowVisible())
//{
// SetForegroundWindow();
// ShowWindow(SW_SHOW); //显示主窗口
//}
//else
//{
// ShowWindow(SW_HIDE);
//}
}
else if (uMouseMsg == WM_RBUTTONUP) //鼠标右键响应
...{
CPoint Point;
GetCursorPos( &Point );
SetForegroundWindow();
m_trayMenuPop->TrackPopupMenu(TPM_RIGHTALIGN | TPM_BOTTOMALIGN, Point.x , Point.y , this , NULL);
AfxGetMainWnd()->PostMessage(WM_NULL , 0 , 0);
}
}
else if(message == WM_ACTIVATE_CAPTURE)
...{
screenDlg.SetOverPopWindow(NULL, SW_HIDE);
PopScreenCaptureDlg();
}
return CDialog::WindowProc(message, wParam, lParam);
}