MFC之系統托盤實現

MFC之系統托盤實現與應用


系統托盤大家應該都瞭解,如果程序需要常時間運行,將程序縮小到托盤中是個不錯的選擇。

現在看看系統托盤應該怎麼實現:

一、NOTIFYICONDATA結構體

首先,必須知道一個結構體NOTIFYICONDATA

 

,這是MFC中包含系統需要的用來傳遞托盤區域消息的信息結構體,有了它,我們今天的任務就完全可以輕鬆完成了!


     這時候,我們可以在我們的類中申明一個NOTIFYICONDATA的成員變量爲m_nid。

接下來,我們可以給這個結構體變量賦我們想要的值了,記住賦值語句要寫在OnInitDialog初始化窗口函數裏,不要寫在構造函數中,否則將會無效。

m_nid.cbSize = sizeof( NOTIFYICONDATA );

m_nid.hWnd = m_hWnd; 
m_nid.uID = IDR_MAINFRAME; 
m_nid.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
m_nid.uCallbackMessage = WM_SYSTEMTRAY;    //自定義消息
m_nid.hIcon = m_hIcon;                                               
strcpy(m_nid.szTip, "認證系統客戶端");

::Shell_NotifyIcon(NIM_ADD, &m_nid);

然後,讓我們一句句的解析這段代碼,

m_nid.cbSize = sizeof( NOTIFYICONDATA );

cbSize表示結構體的大小,以字節爲單位,這裏賦值了NOTIFYICONDATA的結構體標準大小就行了,用sizeof函數就能獲得其字節大小

m_nid.hWnd = m_hWnd; 

hWnd是你想要賦予托盤的窗口句柄,MFC的窗口類中因爲都是繼承CDialog類,所以其中會有一個成員變量是m_hWnd保存着當前實例窗口的具體句柄,我們將其賦值給它就行了

m_nid.uID = IDR_MAINFRAME; 

uID指的是應用程序定義的任務欄圖標的標識符,簡單的時候就是圖片圖標的ID,這裏的ID你可以進入工程下的ResourceView中找到Icon文件夾下的圖標,裏面的ID號就是我們現在要賦值的具體ID,Shell_NotifyIcon函數調用時,hWnd和UID成員用來標示具體要操作的圖標,可以通過多次的調用,來實現不同uID將多個圖標關聯到一個窗口hWnd上,從而實現托盤圖標切換的效果。當然你也可以在此處自定義一個ID使用。

m_nid.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;

uFlags表明具體哪些其他成員爲合法數據,簡單的說就是隻有在uFlags中提到過的變量,才能發揮其作用,具體uFlags可以由以下一些成員組合:

NIF_ICON     表示hicon成員起作用。

NIF_MESSAGE  表示uCallbackMessage成員起作用

NIF_TIP      表示szTip成員起作用

當然還有許多別的如:NIF_STATE,NIF_INFO,NIF_GUID,這裏就具體先介紹上面三個,其他想了解的話可以具體查msdn

m_nid.uCallbackMessage = WM_SYSTEMTRAY; 

uCallbackMessage是應用程序定義的消息標示,當鼠標在托盤鼠標上點擊事件的時候,程序的WM_SYSTEMTRAY就會被髮出,我們可以爲WM_SYSTEMTRAY定義一個消息響應函數,進行處理。也可以在WindowProc函數中就能獲得的該消息,從而做出事件響應,如下:

        switch(message)
{
case WM_SYSTEMTRAY:  //自定義消息

           //具體響應消息

        break; 

        }

其中,大家可以看出WM_SYSTEMTRAY不是系統消息,而是自定義的一個消息,用於表示這個特殊的事件發生了,至於怎麼定義呢,就是用宏了

#define WM_SYSTEMTRAY WM_USER+1

這裏解釋下,爲什麼WM_SYSTEMTRAY要宏定義成WM_USER+1呢,據我瞭解WM_USER是系統消息中的最後一個,也就是說這樣定義就不會和系統的消息衝突成一個同樣的值。

m_nid.hIcon = m_hIcon;  

增加、修改或刪除的圖片句柄,用於控制托盤的圖標,m_hIcon是自定義的一個窗口圖標句柄

HICON m_hIcon;

m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

當然你可以直接將m_nid.hIcon = m_hIcon 改成 m_nid.hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME)

strcpy(m_nid.szTip, "認證系統客戶端");

szTip是一個字符串指針,是在鼠標放在圖標上的時候,會出現的提示消息。

::Shell_NotifyIcon(NIM_ADD, &m_nid);

最後一個是一個全局函數 BOOL Shell_NotifyIcon(DWORD dwMessage,PNOTIFYICONDATA ipdata);

參數dwMessage表示要執行的操作,可選值爲:

NIM_ADD      表示在托盤區域增加圖標

NIM_DELETE   表示刪除托盤區域的圖標

NIM_MODIFY   表示修改托盤區域的圖標

NIM_SETFOCUS 表示聚焦到托盤圖標上

第二個參數就是我們上面介紹過的NOTIFYICONDATA結構體的指針了。

如果操作成功函數會返回TRUE,否則返回FALSE。


///////////////////////////////////////////////////////////////////////////////////

OK,托盤的實現就是這麼簡單的啦,但是如果你想具體深入瞭解,可以查看MSDN裏面具體的解釋,也可以跟本人溝通

下面介紹下應用,具體的應用情況很多。

我們就來簡單的講一下,怎麼實現窗口隱藏後,雙擊托盤使窗口再出現,和右擊托盤出現退出窗口的實現

上面叫到了自定義的消息,在WindowProc函數中,我們可以具體實現

switch(message)
{
case WM_SYSTEMTRAY:  //自定義消息

           if (lParam == WM_LBUTTONDBLCLK)
{  
ShowWindow(SW_SHOWNORMAL);
}

        break; 

        }

上面的代碼就實現了,雙擊托盤實現顯示窗口的代碼,非常簡單,我們就不具體剖析了。

要實現右擊托盤顯示彈出窗口,我們必須先在資源中創建一個菜單,然後加入以下代碼

                case WM_SYSTEMTRAY:  //自定義消息    
if (lParam == WM_RBUTTONDOWN)
{  
//右擊彈出托盤菜單
CMenu menu;
menu.LoadMenu(IDR_MENU1);
CMenu *pPopUp=menu.GetSubMenu(0);
CPoint pt; 
GetCursorPos(&pt); 

SetForegroundWindow(); 
pPopUp->TrackPopupMenu(TPM_RIGHTBUTTON,pt.x,pt.y,this); 
PostMessage(WM_NULL,0,0);
}
break;

代碼中,剛開始定義了一個CMenu的對象,然後將我們之前創建的菜單ID加載進去,然後獲得鼠標當前的位置,在這個位置上將菜單顯示出來

。其他的,大家自己發現和探索吧。




另外注意點擊對話框的關閉按鈕退出時,刪除系統化托盤圖標。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章