Windows95/98/NT/2000/XP中,任務欄的右邊(托盤)常駐幾個圖標,如輸入法切換圖標、音量控制圖標等,此外我們還經常遇到擁有托盤圖標的軟件,如金山詞霸、有實時監測功能的殺毒軟件等。這些軟件在後臺運行,通常不佔用太多的屏幕資源,只在通知欄上放一個小小的標誌。必要時我們可以通過用鼠標點擊圖標對其進行菜單操作或激活其主窗口。有時我們自己編寫的程序也希望有類似的效果,本文詳細地介紹用VC++6.0設計這種托盤圖標程序的方法。
NOTIFYICONDATA結構
---- NOTIFYICONDATA結構包含了系統用來處理托盤圖標的信息,它包括選擇的圖標、回調消息、提示消息、圖標對應的窗口等內容。其定義爲:
typedef struct _NOTIFYICONDATA { DWORD cbSize; //以字節爲單位的這個結構的大小 HWND hWnd; //接收托盤圖標通知消息的窗口句柄 UINT uID; //應用程序定義的該圖標的ID號 UINT uFlags; //設置該圖標的屬性 UINT uCallbackMessage; //應用程序定義的消息ID號,此消息傳遞給hWnd HICON hIcon; //圖標的句柄 char szTip[64]; //鼠標停留在圖標上顯示的提示信息 } NOTIFYICONDATA, *PNOTIFYICONDATA; |
該結構中,成員uFlags可以使下列之一或組合:
NIF_ICON 設置成員hIcon有效
NIF_MESSAGE 設置成員uCallbackMessage有效
NIF_TIP 設置成員szTip有效
Shell_NotifyIcon函數
---- 全局函數Shell_NotifyIcon() 用於在托盤上增加、刪除或修改圖標。其原型爲:
WINSHELLAPI BOOL WINAPI Shell_NotifyIcon( DWORD dwMessage, PNOTIFYICONDATA pnid); |
---Pnid是NOTIFYICONDATA結構的指針; dwMessage是被傳遞的消息,可以是以下消息之一:
NIM_ADD 增加圖標
NIM_DELETE 刪除圖標
NIM_MODIFY 修改圖標
托盤圖標程序設計示例
---- 首先我們用AppWizard創建一個基於文檔/視圖結構的單文檔應用程序My。在CMainFrame類中加入NOTIFYICONDATA結構的保護成員變量m_tnid,並在其OnCreate函數中return語句前加入生成托盤圖標的代碼:
m_tnid.cbSize=sizeof(NOTIFYICONDATA); m_tnid.hWnd=this->m_hWnd; m_tnid.uFlags=NIF_MESSAGE|NIF_ICON|NIF_TIP; m_tnid.uCallbackMessage=MYWM_NOTIFYICON; //用戶定義的回調消息 CString szToolTip; szToolTip=_T("托盤圖標實例"); _tcscpy(m_tnid.szTip, szToolTip); m_tnid.uID=IDR_MAINFRAME; HICON hIcon; hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME); m_tnid.hIcon=hIcon; ::Shell_NotifyIcon(NIM_ADD,&m_tnid); if(hIcon)::DestroyIcon(hIcon); |
----回調消息的ID應在主框架類的頭函數中定義:
#define MYWM_NOTIFYICON WM_USER+1 |
----爲了處理圖標回調消息,如鼠標左鍵雙擊、鼠標右鍵單擊消息,我們重載WindowProc()函數。此外,我們還希望在主框架窗口最小化時圖標不在任務欄空白區出現,在此函數中同時作相應處理。
LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { switch(message){ case MYWM_NOTIFYICON: //如果是用戶定義的消息 if(lParam==WM_LBUTTONDBLCLK) { //鼠標雙擊時主窗口出現 AfxGetApp()->m_pMainWnd->ShowWindow(SW_SHOW); } else if(lParam==WM_RBUTTONDOWN){ //鼠標右鍵單擊彈出菜單 CMenu menu; menu.LoadMenu(IDR_RIGHT_MENU); //載入事先定義的菜單 CMenu* pMenu=menu.GetSubMenu(0); CPoint pos; GetCursorPos(&pos); pMenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,pos.x,pos.y,AfxGetMainWnd()); } break; case WM_SYSCOMMAND: //如果是系統消息 if(wParam==SC_MINIMIZE){ //接收到最小化消息時主窗口隱藏 AfxGetApp()->m_pMainWnd->ShowWindow(SW_HIDE); return 0; } break; } return CFrameWnd::WindowProc(message, wParam, lParam); } |
---- 爲使應用程序退出時圖標消失,映射WM_DESTROY消息,在OnDestroy()函數中加入:
::Shell_NotifyIcon(NIM_DELETE,&m_tnid); |
---- 至此,托盤圖標程序的常規功能我們均已實現。我們還可以通過Shell_NotifyIcon()函數的調用實現不同狀態下圖標的改變,就像金山詞霸在主窗口打開與暫停取詞時圖標有所改變一樣。
經試驗完全可行