1. 程式人生 > >MFC系統托盤的實現

MFC系統托盤的實現

怎麼實現呢?這裡需要運用到的Windows API函式:

BOOL Shell_NotifyIcon(
    DWORD dwMessage, 
    PNOTIFYICONDATA lpdata
);
          函數了裡面的引數對於實現不同的效果尤其重要,包括托盤圖示、托盤選單等等。那麼我們來了解一下兩個引數吧:

dwMessage可以取以下值:

NIM_ADD 向托盤中加入一個圖示
NIM_MODIFY 修改托盤中的圖示
NIM_DELETE 從托盤中刪除一個圖示

引數pnid是NOTIFYICONDATA結構的一個引用。該結構的原型如下:

[cpp] view plain
 copy  print?
  1. typedefstruct _NOTIFYICONDATA {   
  2.     DWORD cbSize; // 結構的大小,必須在程式中給出
  3.     HWND hWnd;    // 程式中將要接收托盤訊息的視窗控制代碼
  4.     UINT uID;     // 應用程式中定義的托盤圖示ID,此引數用作標識
  5.     UINT uFlags;  //設定屬性 標記下邊3個引數是否有效
  6.     UINT uCallbackMessage;// 自定義的訊息ID值
  7.     HICON hIcon;//顯示在系統托盤上的Icon的控制代碼
  8.     #if (_WIN32_IE < 0x0500)
  9.         TCHAR szTip[64;// 用於圖示顯示的提示字串
  10.     #else
  11.         TCHAR szTip[128];  
  12.     #endif
  13.     #if (_WIN32_IE >= 0x0500)
  14.         DWORD dwState;   
  15.         DWORD dwStateMask;   
  16.         TCHAR szInfo[256];   
  17.         union {  
  18.             UINT  uTimeout;   
  19.             UINT  uVersion;   
  20.         } DUMMYUNIONNAME;  
  21.         TCHAR szInfoTitle[64];   
  22.         DWORD dwInfoFlags;   
  23.     #endif
  24.     #if (_WIN32_IE >= 0x600)
  25.         GUID guidItem;  
  26.     #endif
  27. } NOTIFYICONDATA, *PNOTIFYICONDATA;   
           具體步驟如下:

1.在程式中增加一個私有的NOTIFYICONDAT物件

[cpp] view plain copy  print?
  1. private:  
  2.         NOTIFYICONDATA m_tnid;  
2.在初始化視窗時對NOTIFYICONDAT物件初始化 用Shell_NotifyIcon函式進行註冊 [cpp] view plain copy  print?
  1. m_notify.cbSize=sizeof NOTIFYICONDATA;  
  2. m_notify.hWnd=this->m_hWnd;    
  3. m_notify.uID=IDR_MAINFRAME;  
  4. m_notify.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));  
  5. strcpy(m_notify.szTip,"Michael_Chen is a good man");  
  6. m_notify.uCallbackMessage=WM_USER_NOTIFYICON;  
  7. m_notify.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP; //OK,下面就是托盤產生了. 
  8. Shell_NotifyIcon(NIM_ADD,&m_notify);  
3.增加自定義的訊息處理函式或者過載WindowProc函式,在訊息處理函式或WindowProc函式中對自定義的訊息進行處理

1)運用自定義訊息

i,WM_USER_NOTIFYICON是自定義的訊息 在標頭檔案中進行宣告;

[cpp] view plain copy  print?
  1. #define WM_USER_NOTIFYICON WM_USER+1
ii,在.h檔案中宣告訊息函式原型 [cpp] view plain copy  print?
  1. afx_msg LRESULT OnNotifyMsg(WPARAM wparam,LPARAM lparam);  
iii,在.cpp檔案中進行訊息對映 [cpp] view plain copy  print?
  1. BEGIN_MESSAGE_MAP(CNotifyiconDlg, CDialog)  
  2.     //{{AFX_MSG_MAP(CNotifyiconDlg)
  3.                  ...  
  4.     ON_MESSAGE(WM_USER_NOTIFYICON,OnNotifyMsg)  
  5.     //}}AFX_MSG_MAP
  6. END_MESSAGE_MAP()  
iiii,在.cpp檔案中新增自定義的訊息響應程式碼,左鍵雙擊彈出應用程式主視窗,右鍵單擊彈出選單。 [cpp] view plain copy  print?
  1. LRESULT  CNotifyiconDlg::OnNotifyMsg(WPARAM wparam,LPARAM lparam)  
  2. //wParam接收的是圖示的ID,而lParam接收的是滑鼠的行為   
  3. {  
  4.     if(wparam!=IDR_MAINFRAME)     
  5.         return    1;     
  6.     switch(lparam)     
  7.     {     
  8.     case  WM_RBUTTONUP://右鍵起來時彈出快捷選單,這裡只有一個“關閉”   
  9.         {       
  10.             LPPOINT    lpoint=new    tagPOINT;     
  11.             ::GetCursorPos(lpoint);//得到滑鼠位置   
  12.             CMenu    menu;     
  13.             menu.CreatePopupMenu();//宣告一個彈出式選單   
  14.             //增加選單項“關閉”,點選則傳送訊息WM_DESTROY給主視窗(已   
  15.             //隱藏),將程式結束。   
  16.             menu.AppendMenu(MF_STRING,WM_DESTROY,"關閉");       
  17.             //確定彈出式選單的位置   
  18.             menu.TrackPopupMenu(TPM_LEFTALIGN,lpoint->x,lpoint->y,this);     
  19.             //資源回收   
  20.             HMENU    hmenu=menu.Detach();     
  21.             menu.DestroyMenu();     
  22.             delete    lpoint;     
  23.         }     
  24.         break;     
  25.     case    WM_LBUTTONDBLCLK://雙擊左鍵的處理   
  26.         {     
  27.             this->ShowWindow(SW_SHOW);//簡單的顯示主視窗完事兒   
  28.         }     
  29.         break;     
  30.     }      
  31.     return 0;  
  32. }  

2)過載WindowProc函式

i,過載WindowProc函式(方法略)

ii,在WindowProc中增加的訊息相應程式碼

[cpp] view plain copy  print?
  1. //WindowProc中增加的程式碼
  2. LRESULT CNotifyiconDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)   
  3. {  
  4.     // TODO: Add your specialized code here and/or call the base class
  5.     switch(message) //判斷訊息型別
  6.     {   
  7.     case WM_USER_NOTIFYICON:   
  8.         //如果是使用者定義的訊息 
  9.         if(lParam==WM_LBUTTONDBLCLK)  
  10.         {   
  11.             //滑鼠雙擊時主窗口出現 
  12.             if(AfxGetApp()->m_pMainWnd->IsWindowVisible()) //判斷視窗當前狀態
  13.             {  
  14.                 AfxGetApp()->m_pMainWnd->ShowWindow(SW_HIDE); //隱藏視窗
  15.             }  
  16.             else
  17.             {  
  18.                 AfxGetApp()->m_pMainWnd->ShowWindow(SW_SHOW); //顯示視窗
  19.             }  
  20.         }   
  21.         elseif(lParam==WM_RBUTTONDOWN)  
  22.         { //滑鼠右鍵單擊彈出選單 
  23.             CMenu menu;   
  24.             menu.LoadMenu(IDR_MENU1); //載入事先定義的選單 
  25.             CMenu *pMenu=menu.GetSubMenu(0);   
  26.             CPoint pos;   
  27.             GetCursorPos(&pos);   
  28.             pMenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,pos.x,pos.y,AfxGetMainWnd());   
  29.         }   
  30.