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