mfc實現系統托盤
Windows作業系統中的某些程式執行時不顯示執行視窗,只在工作列上顯示一個圖示,表示程式正在執行,使用者可以通過滑鼠與應用程式互動,比如金山毒霸等應用程式,我們有時也需要編制一些僅在後臺執行的類似程式,為了不干擾前臺程式的執行介面和不顯示不必要的視窗,應使程式執行時的主視窗不可見。同時將一個圖示顯示在工作列右端靜態通告區中並響應使用者的滑鼠動作。下面介紹Visual C++開發這類程式的設計方法。
一、隱藏程式的主視窗
首先,要使程式的主視窗不可見,並且不在工作列上出現任務按鈕,要做到這兩點,需分別設定主邊框視窗的風格和擴充套件風格:
BOOL CMainFrame::PreCreateWindow(CreateSTRUCT& cs)
{
cs.style =WS_POPUP;//使主視窗不可見
cs.dwExStyle |=WS_EX_TOOLWINDOW;//不顯示任務按鈕
return CFrameWnd::PreCreateWindow(cs);
}
二、將表示程式執行的圖示加入工作列
在主框架視窗的CMainFrame::OnCreate()函式中呼叫上述函式,就可以在任務條上顯示圖示這一步是利用系統API函式Shell_NotifyIcon()將一個圖示顯示在工作列的通告區中。該函式的原型為:在呼叫該函式之前,需要確定其引數的取值。其中Shell_NotifyIcon()函式的第一個引數是一個預定義的訊息,可以取如下值之一:NIM_ADD、NIM_Delete或NIM_MODIFY,分別表示新增圖示、刪除圖示或修改圖示。另一個引數為指向NOTIFYICONDATA型別的指標。其原型為:
typedef struct _NOTIFYICONDATA {
DWORD cbSize;
HWND hWnd;
UINT uID;
UINT uFlags;
UINT uCallbackMessage;
HICON hIcon;
charszTip[64]; }
NOTIFYICONDATA
在該結構的成員中,cbSize為該結構所佔的位元組數,hWnd為接受該圖示所發出的訊息的視窗的控制代碼(滑鼠在工作列上程式圖示上動作時圖示將發出訊息,這個訊息使用者要自己定義),uID為被顯示圖示的ID,uFlags指明其餘的幾個成員(hIcon、uCallBackMessage和szTip)的值是否有效,uCallbackMessage為一個使用者自定義的訊息,當用戶在該圖示上作用一些滑鼠動作時,圖示將嚮應用程式的主框架視窗(hWnd成員中指定的視窗)發出該訊息,。hIcon為將在工作列上被顯示圖示的控制代碼,szTip滑鼠停留在該圖示上時顯示的字串。
int CMainFrame::OnCreate(LPCreateSTRUCT lpCreateStruct)
{
NOTIFYICONDATA tnd;
tnd.cbSize=sizeof(NOTIFYICONDATA);
tnd.hWnd=this->m_hWnd;
tnd.uID=IDR_MAINFRAME;
tnd.uFlags=NIF_MESSAGE|NIF_ICON|NIF_TIP;
tnd.uCallbackMessage=WM_MYMESSAGE;
file://使用者自定義的訊息,即滑鼠在工作列上程式圖示上動作時圖示傳送的訊息
tnd.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));
strcpy(tnd.szTip,”測試程式”);//圖示提示為”測試程式”
Shell_NotifyIcon(NIM_ADD,&tnd);//向工作列新增圖示
}
三、使用者與程式互動的實現
使用者進行互動,也就是當用戶在該圖示上單擊或雙擊滑鼠左鍵或右鍵時要執行相應的操作,至少也要響應使用者終止該程式的意願。上面已經提到,當用戶在圖示上進行滑鼠動作時,將向hWnd成員中指定的視窗發出自定義的訊息,該訊息為uCallbackMessage成員所指定的WM_MYESSAGE,取值為WM_USER+101(如何自定義訊息,我就不多說了)。我們要實現任務就是在hWnd視窗中響應該自定義訊息:
void CMainFrame::OnMYMESSAGE(WPARAM wParam,LPARAM lParam)
{
UINT uID;//發出該訊息的圖示的ID
UINT uMouseMsg;//滑鼠動作
POINT pt;
uID=(UINT) wParam;
uMouseMsg=(UINT) lParam;
if(uMouseMsg==WM_RBUTTONDOWN)//如果是單擊右鍵
{
switch(uID)
{
case IDR_MAINFRAME://如果是我們的圖示
GetCursorPos(&pt);//取得滑鼠位置
AfxGetApp( )-> m_pMainWnd->ShowWindow(SW_SHOWNORMAL);//顯示程式視窗
break;
default:
}
}
return;
}
四、程式結束時刪除程式圖示
當程式結束時,需要刪去通告區中的圖示,這時還應該呼叫Shell_NotifyIcon函式,只不過第一個引數是表示刪除圖示的NIM_Delete了:
void CMainFrame::~CmainFrame()
{
NOTIFYICONDATA tnid;
tnid.cbSize=sizeof(NOTIFYICONDATA);
tnid.hWnd=this->m_hWnd;
tnid.uID=IDR_MAINFRAME;//保證刪除的是我們的圖示
Shell_NotifyIcon(NIM_Delete,&tnid);
}
上述實現步驟可以實現托盤程式,筆者在開發的IC卡程式中就應用了以上技術,希望可以對朋友們有所幫助