在VC++中,想實現最小化MFC程序的時候,最小化到系統托盤,需要調用NOTIFYICONDATA類
下面我們就來講解一下如何簡單實現一個系統托盤我們以對話框程序爲列
第一步:在Dlg類中//定義一個NOTIFYICONDATA類的成員變量,用來設置托盤
NOTIFYICONDATA NotifyIcon;
第二步:聲明一個消息響應函數 afx_msg void OnNotifyIcon(WPARAM wParam,LPARAM IParam);
上面那條代碼也放在Dlg的頭文件中
第三步:定義一個自定義消息 #define WM_NC WM_USER+1
上面那條代碼也在Dlg的頭文件中聲明
註冊消息 ON_MESSAGE(WM_NC,OnNotifyIcon)
上面那條代碼在Dlg類中
第四步:在Dlg頭文件中添加一個函數用來響應點擊最小化按鈕
void changeMini();
並在Dlg類中實現這個函數
//響應最小化消息
void CChangeScreenDlg::changeMini()
{
ShowWindow(SW_HIDE);
NotifyIcon.cbSize=sizeof(NOTIFYICONDATA);
NotifyIcon.hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
NotifyIcon.hWnd=m_hWnd;
lstrcpy(NotifyIcon.szTip,"MediaCraft EMMG");
NotifyIcon.uCallbackMessage=WM_NC;
NotifyIcon.uFlags=NIF_ICON | NIF_MESSAGE | NIF_TIP;
Shell_NotifyIcon(NIM_ADD,&NotifyIcon);
}
第五步:截獲最小化事件
在Dlg類中找到OnSysCommand函數
修改代碼如下
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
//攔截最小化事件
if(nID==SC_MINIMIZE)
{
//ToTray();
//用我們自己的消息響應最小化事件
changeMini();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
第六步:響應托盤的鼠標事件也是實現我們第二部聲明的消息響應函數
void CChangeScreenDlg::OnNotifyIcon(WPARAM wParam,LPARAM IParam)
{
if ((IParam == WM_LBUTTONDOWN) || (IParam == WM_RBUTTONDOWN))
{
ModifyStyleEx(0,WS_EX_TOPMOST);
ShowWindow(SW_SHOW);
}
}
最後一步:在類的析構函數中記得銷燬托盤圖標對象
Shell_NotifyIcon(NIM_DELETE, &NotifyIcon);
傻朋提示:以上NOTIFYICONDATA類的一些具體參數,請參閱MSDN
一、NOTIFYICONDATA結構
NOTIFYICONDATA結構包含了系統用來處理托盤圖標的信息,它包括選擇的圖標、回調消息、提示消息、圖標對應的窗口等內容。其定義爲:
typedef struct _NOTIFYICONDATA {
DWORDcbSize;
//以字節爲單位的這個結構的大小
HWND hWnd;
//接收托盤圖標通知消息的窗口句柄
UINT uID; //應用程序定義的該圖標的ID號
UINTuFlags;
//設置該圖標的屬性
UINT uCallbackMessage;
//應用程序定義的消息ID號,此消息傳遞給hWnd
HICONhIcon;
//圖標的句柄
charszTip[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創建一個基於對話框的應用程序CUserDlg。m_nid爲類成員變量
voidCUserDlg::ToTray()
{
m_nid.cbSize = (DWORD)sizeof(NOTIFYICONDATA);
m_nid.hWnd = this->m_hWnd;
m_nid.uID = IDR_MAINFRAME;
m_nid.uFlags = NIF_ICON|NIF_MESSAGE|NIF_TIP ;
m_nid.uCallbackMessage = WM_SHOWTASK;
//自定義的消息名稱 WM_SHOWTASK
頭函數中定義爲WM_USER+1
m_nid.hIcon = LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));
strcpy(m_nid.szTip,"托盤圖標");//當鼠標放在上面時,所顯示的內容
Shell_NotifyIcon(NIM_ADD,&m_nid);//在托盤區添加圖標
}
四.添加消息WM_SHOWTASK的響應函數afx_msg LRESULT onShowTask(WPARAM wParam,LPARAM lParam);
在BEGIN_MESSAGE_MAP(CUserDlg,CDialog)和END_MESSAGE_MAP()之間加代碼:
ON_MESSAGE(WM_SHOWTASK,onShowTask)
編寫該函數:
LRESULTCUserDlg::onShowTask(WPARAM wParam,LPARAM lParam) //wParam接收的是圖標的ID,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_SHOWNORMAL);//簡單的顯示主窗口
}
break;
}
return 0;
}
然後在OnInitDialog函數中調用ToTray();
五爲使應用程序退出時圖標消失,映射WM_DESTROY消息,在OnDestroy()函數中加入:
::Shell_NotifyIcon(NIM_DELETE,&m_tnid);
六。至此,托盤圖標程序的常規功能我們均已實現。我們還可以通過Shell_NotifyIcon()函數的調用實現不同狀態下圖標的改變,就象金山詞霸在主窗口打開與暫停取詞時圖標有所改變一樣。它常 用來顯示一些系統的狀態。如:系統時間,音量控制以及其它的一些圖標
總體的思想就是這樣的