MFC 系統托盤圖示實現,包括雙擊圖示和右鍵圖示選單
首先,必須知道一個結構體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上,從而實現托盤圖示切換的效果
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就會被髮出,我們只要在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載入進去,然後獲得滑鼠當前的位置,在這個位置上將選單顯示出來
最後退出要刪除圖示: Shell_NotifyIcon(NIM_DELETE,&m_traydata);