(一) 原理
1、最小化的原理:首先要將視窗隱藏,然後 在右下角繪製表徵圖。
2、恢複的原理:將視窗顯示,再將托盤中的圖片刪除。
(二)程式實現
1、自訂訊息WM_SHOWTASK: #define WM_SHOWTASK (WM_USER +1)
2、在MFC的::OnSysCommand(UINT nID, LPARAM lParam)函數體中增加一個命令響應
if(nID==SC_MINIMIZE)
ToTray(); //最小化到托盤的函數
3、在訊息映射中添加 ON_MESSAGE(WM_SHOWTASK,OnShowTask),其中WM_SHOWTASK是訊息名,OnShowTask是自己定義的訊息響應函數,後面有說明。
(三)具體函數內容
1、最小化到托盤函數
void CMyDlg::ToTray()
{
NOTIFYICONDATA nid;
nid.cbSize=(DWORD)sizeof(NOTIFYICONDATA);
nid.hWnd=this->m_hWnd;
nid.uID=IDR_MAINFRAME;
nid.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP ;
nid.uCallbackMessage=WM_SHOWTASK;//自訂的訊息名稱
nid.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));
strcpy(nid.szTip,"程式名稱"); //資訊提示條
Shell_NotifyIcon(NIM_ADD,&nid); //在托盤區添加表徵圖
ShowWindow(SW_HIDE); //隱藏主視窗
}
2、恢複介面函數在標頭檔中定義訊息響應函數
afx_msg LRESULT OnShowTask(WPARAM wParam,LPARAM lParam) ;//wParam接收的是表徵圖的ID,而lParam接收的是滑鼠的行為
LRESULT CMyDlg::OnShowTask(WPARAM wParam,LPARAM lParam)
{
if(wParam!=IDR_MAINFRAME)
return 1;
switch(lParam)
{
case WM_RBUTTONUP://右鍵起來時彈出捷徑功能表,這裡只有一個“關閉”
{
LPPOINT lpoint=new tagPOINT;
::GetCursorPos(lpoint);//得到滑鼠位置
CMenu menu;
menu.CreatePopupMenu();//聲明一個彈出式菜單
//增加功能表項目“關閉”,點擊則發送訊息WM_DESTROY給主視窗(已
//隱藏),將程式結束。
menu.AppendMenu(MF_STRING,WM_DESTROY,"關閉");
//確定彈出式菜單的位置
menu.TrackPopupMenu(TPM_LEFTALIGN,lpoint->x,lpoint->y,this);
//資源回收
HMENU hmenu=menu.Detach();
menu.DestroyMenu();
delete lpoint;
}
break;
case WM_LBUTTONDBLCLK://雙擊左鍵的處理
{
this->ShowWindow(SW_SHOW);//簡單的顯示主視窗完事兒
DeleteTray();
}
break;
default:
break;
}
return 0;
}
3、刪除托盤表徵圖函數void CMyDlg::DeleteTray()
{
NOTIFYICONDATA nid;
nid.cbSize=(DWORD)sizeof(NOTIFYICONDATA);
nid.hWnd=this->m_hWnd;
nid.uID=IDR_MAINFRAME;
nid.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP ;
nid.uCallbackMessage=WM_SHOWTASK;//自訂的訊息名稱
nid.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));
strcpy(nid.szTip,"程式名稱"); //資訊提示條為“計劃任務提醒”
Shell_NotifyIcon(NIM_DELETE,&nid); //在托盤區刪除表徵圖
}
/***該系統需要處理的工作列狀態區的訊息***/
typedef struct _NOTIFYICONDATA {
DWORD cbSize; //結構體的大小,以位元組為單位
HWND hWnd; //視窗的控制代碼
UINT uID; //應用程式定義的工作列表徵圖的標識符
UINT uFlags; //此成員表明具體哪些其他成員為合法資料
UINT uCallbackMessage; //應用程式定義的訊息標示
HICON hIcon; //增加、修改或刪除的表徵圖的控制代碼
TCHAR szTip[64]; //指向一個以\0結束的字串的指標
DWORD dwState; //Version 5.0,表徵圖的狀態
DWORD dwStateMask; //Version 5.0. 指明dwState成員的那些位可以被設定或者訪問
TCHAR szInfo[256]; //指向一個以\0結束的字串的指標,字串的內容為氣球提示內容
union {
UINT uTimeout; //表示氣球提示逾時的時間,單位為毫秒,此時間後氣球提示將消失
UINT uVersion; //用來設定使用Windows 95 還是 Windows 2000風格的表徵圖訊息介面
};
TCHAR szInfoTitle[64]; //指向一個以\0結束的字串的指標。字串的內容為氣球提示的標題
DWORD dwInfoFlags; //設定此成員用來給氣球提示框增加一個表徵圖,增加的表徵圖出現在氣球提示標題的左側
GUID guidItem; //保留
HICON hBalloonIcon; //用於Windows Vista或更高版本的自訂氣球表徵圖
} NOTIFYICONDATA, *PNOTIFYICONDATA;
註:在單文檔中,在架構類中添加OnSysCommd訊息響應
單文檔的托盤程式
一、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建立一個不基於文檔/視圖結構的應用程式Tray。我們並不想在應用程式啟動時顯示主視窗,所以刪除應用程式類CTrayApp中InitInstance()函數中的以下兩句使主視窗顯示的代碼:
pFrame->ActivateFrame();
pFrame->ShowWindow(SW_SHOW);
在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()函數的調用實現不同狀態標的改變,就象金山詞霸在主視窗開啟與暫停取詞時表徵圖有所改變一樣。
---- 本程式在VC++6.0,Windows98/2000 Professional下調試通過。