Minimize your app to systray in 8 easy steps
By Yasar Arslan. From codeproject
这篇文章内容比较基础,最近看到觉得有用,顺便翻译一下
有空可以写一个自己的TrayIcon类,化简这些原始的操作。
Introduction
这篇文章解析了 Shell_NotifyIcon
这个函数用法--用来建立你自己的应用程序的系统托盘图标.
这篇文章给了基本的缩小到托盘的操作过程并让你从中了解.
这篇文章提供8个简单的步骤让你成功的实现在你的程序中建立系统托盘图标.
源代码提供了一个基于对话框的演示程序.
Tray Icons
为了用托盘图标你需要用一个shell函数 :)
BOOL Shell_NotifyIcon( DWORD dwMessage, PNOTIFYICONDATA pnid );
The dwMessage
可选的参数包括 the NIM_ADD,NIM_DELETE and NIM_MODIFY
功能分别是添加删除以及修改图标于系统图标.
PNOTIFYICONDATA
结构包括这些系统需要处理的任务图标状态区域消息等信息.
typedef struct _NOTIFYICONDATA {
DWORD cbSize;
HWND hWnd;
UINT uID;
UINT uFlags;
UINT uCallbackMessage;
HICON hIcon;
#if (_WIN32_IE < 0x0500)
TCHAR szTip[64];
#else
TCHAR szTip[128];
#endif #if (_WIN32_IE >= 0x0500)
DWORD dwState;
DWORD dwStateMask;
TCHAR szInfo[256];
union {
UINT uTimeout;
UINT uVersion;
} DUMMYUNIONNAME;
TCHAR szInfoTitle[64];
DWORD dwInfoFlags;
#endif #if (_WIN32_IE >= 0x600)
GUID guidItem;
#endif
} NOTIFYICONDATA, *PNOTIFYICONDATA;
*Note: 更完全的信息可以去参考MSDN
Creating the Application
Create a new VC++ dialog based project and call it TrayMin.
创建一个名叫TrayMin的基于对话框的VC++工程
Step: 1
自定义消息于 TrayMinDlg.h 头文件.
#define WM_TRAY_MESSAGE (WM_USER + 1)
The WM_USER
常量用来帮助用户定义自己的消息被用来建立个人的窗口类, 定义时通常用这种格式 WM_USER+X
, 这里 X 是一个整形变量.
*更详细的看MSDN
Step: 2
现在在Now add the DECLARE_MESSAGE_MAP() 之前添加下面的用户函数吧( TrayMinDlg.h file) afx_msg void OnTrayNotify(WPARAM wParam, LPARAM lParam);
当添加一个图标到托盘时这有一个图标的回调消息,注意到 NOTIFYICONDATA
结构中有uCallbackMessage成员是回调消息识别的关键,它会被传给NIM_ADD(我们之后将会见到更详细的)。当添加托盘图标这个事件发生时,系统发送一个回调函数到由hWnd成员对象指定的窗口过程(winproc),wParam 参数可以用来被识别究竟发生了什么操作。lParam参数存放发生事件相关的鼠标或者键盘消息。举个例子,当一个鼠标指针指向一个托盘图标,lParam将包括WM_MOUSEMOVE
Step: 3
现在添加下面的这行在消息宏中(MessageMap)在TrayMinDlg.cpp
ON_MESSAGE(WM_TRAY_MESSAGE,OnTrayNotify)
现在应该是这样的.
BEGIN_MESSAGE_MAP(CTrayMinDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_MESSAGE(WM_TRAY_MESSAGE ,OnTrayNotify)
END_MESSAGE_MAP()
Step: 4
现在在TrayMinDlg.cpp 定义OnTrayNotify函数,不要忘记在函数头部添加afx_msg。
afx_msg void CTrayMinDlg::OnTrayNotify(WPARAM wParam, LPARAM lParam)
{
UINT uID;
UINT uMsg;
uID = (UINT) wParam;
uMsg = (UINT) lParam;
if (uID != 1)
return;
CPoint pt;
switch (uMsg )
{
case WM_LBUTTONDOWN:
GetCursorPos(&pt);
ClientToScreen(&pt);
OnTrayLButtonDown(pt);
break;
case WM_RBUTTONDOWN:
case WM_CONTEXTMENU:
GetCursorPos(&pt);
OnTrayRButtonDown(pt);
break;
}
return;
}
Step: 5
现在在TrayMinDlg类添加两个成员函数来相应鼠标事件。
实现鼠标左键单击的相应
-
函数类型:void
-
函数声明:
OnTrayLButtonDown(CPoint pt)
实现鼠标右键单击的相应
- 函数类型:
void
- 函数声明:
OnTrayRButtonDown(CPoint pt)
OnTrayLButtonDown(CPoint pt)的定义如下
.
void CTrayMinDlg::OnTrayLButtonDown(CPoint pt)
{
MessageBox("You have clicked Left mouse Button ");
}
The Declaration of OnTrayRButtonDown(CPoint pt)
is as following.
void CTrayMinDlg::OnTrayRButtonDown(CPoint pt)
{
m_menu.GetSubMenu(0)->TrackPopupMenu(TPM_BOTTOMALIGN|
TPM_LEFTBUTTON|TPM_RIGHTBUTTON,pt.x,pt.y,this);
}
Step: 6
Add two member variable to the CTrayMinDlg
.
为CTrayMinDlg添加两个成员变量
- Variable Type:
NOTIFYICONDATA
- Variable Name:
m_TrayData
;
- Variable Type:
CMenu
- Variable Name:
m_menu
;
现在添加菜单资源
Step: 7
现在画一个最小化的按钮在对话框设计中
并且添加这个按钮的执行函数
void CShellDlg::OnMinimize()
{
m_TrayData.cbSize = sizeof(NOTIFYICONDATA);
m_TrayData.hWnd = this->m_hWnd;
m_TrayData.uID = 1;
m_TrayData.uCallbackMessage = WM_TRAY_MESSAGE;
m_TrayData.hIcon = this->m_hIcon;
strcpy(m_TrayData.szTip,"My Icon");
m_TrayData.uFlags = NIF_ICON|NIF_MESSAGE;
valid data.
BOOL bSuccess = FALSE;
BOOL BSus = FALSE;
BSus = m_menu.LoadMenu(IDR_MENU1);
if(!(BSus))
MessageBox("Unabled to Loa menu");
bSuccess = Shell_NotifyIcon(NIM_ADD,&m_TrayData);
if(!(bSuccess))
MessageBox("Unable to Set Tary Icon");
else
{
this->ShowWindow(SW_MINIMIZE);
this->ShowWindow(SW_HIDE);
}
}
Step: 8
在退出菜单的执行函数写下如下
Shell_NotifyIcon(NIM_DELETE,&m_TrayData);
DestroyWindow();
现在可以运行程序,并且尝试最小化按钮的使用(他会最小化导系统托盘)。
现在尽情发挥,完善这些步骤,完成自己的系统托盘图标吧!
Yasar Arslan