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卡程序中就應用了以上技術,希望可以對朋友們有所幫助

發佈了13 篇原創文章 · 獲贊 2 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章