1. 程式人生 > >玩轉VC++系統托盤程式(WIN8)

玩轉VC++系統托盤程式(WIN8)



        WINDOWS系統托盤是一個特殊區域,通常在桌面的右下角,也就是工作列的右邊。系統常駐在托盤的程式有時鐘,音量控制,輸入法,網路狀態等。第三方應用如QQ程式也是一個典型的托盤程式,當最小化時企鵝會乖乖的待在螢幕右下角等待主人的呼喚。

    系統托盤的方便之處在於,程式在暫時不用時,將它放到托盤裡,隨用隨叫,不必將其關閉。而QQ在接收到訊息後,也會在托盤中閃動提示,十分人性化。

那麼如何用VC++來開發托盤程式呢?下面會用一個例子來玩轉WINDOWS托盤程式。

首先,定義一下需要的功能。(需求確定)

  1. 程式最小化到托盤。

  2. 右鍵點選,顯示一個選單。

  3. 滑鼠左鍵雙擊托盤圖示,開啟程式。

  4. 程式中點選一個按鈕,改變托盤圖示。

好了,就這麼簡單的Demo,下面看看如何實現。

其次,歸納一下用到的技術點。

  1. 托盤相關API

  2. MFC對滑鼠操作訊息的接收

先來說說托盤相關的APIMFC並沒有直接提高便利的類來支援系統托盤程式設計,我們需要用到SHELLAPI中的Shell_NotifyIcon函式。原型為:

BOOL Shell_NotifyIcon(
    DWORD dwMessage,
    PNOTIFYICONDATA lpdata
);

函式很簡單清晰,只有兩個引數。引數一dwMessage用來指定托盤的動作,這是一個四位元組的值。如下:

  1. NIM_ADD(0X00000000):新增一個系統托盤

  2. NIM_MODIFY(0X00000001):系統托盤的修改

  3. NIM_DELETE(0X00000002):系統托盤的刪除

  4. NIM_SETFOCUS(0X00000003):令系統托盤獲得焦點

  5. NIM_SETVERSION(0X00000004):系統托盤設定版本

引數二PNOTIFYICONDATA是專門為此服務的結構體。原型如下:

typedef struct _NOTIFYICONDATA {
  DWORD cbSize;//結構體的大小,單位是位元組
  HWND  hWnd;//此托盤程式的控制代碼
  UINT  uID;// 系統為托盤區域每個圖示分配的ID
  UINT  uFlags;//簡單的說,就是一個標示
  UINT  uCallbackMessage;//回撥訊息。需要自定義一個訊息,用來接收滑鼠滑過或點選等訊息。
  HICON hIcon;//圖示
  TCHAR szTip[64];//提示文字的大小
  DWORD dwState;//圖示的狀態
  DWORD dwStateMask;//與上面類似
  TCHAR szInfo[256];//顯示在氣泡通知中的文字
  union {
    UINT uTimeout;
    UINT uVersion;
  };
  TCHAR szInfoTitle[64];//氣泡通知的標題
  DWORD dwInfoFlags;//修改氣泡通知相關的標示
  GUID  guidItem;//圖示的GUID
  HICON hBalloonIcon;//氣泡通知的圖示
} NOTIFYICONDATA, *PNOTIFYICONDATA;

再來說說MFC中對滑鼠操作資訊的接收。

其實上面的調查結果一出,這個問題也就迎刃而解了。關鍵在uCallbackMessage。我們會自定義一個訊息,比如就叫做WM_ICON_NOTIFY,當此托盤圖示有滑鼠滑過,懸停或點選,鍵盤操作時回撥這個接收自定義訊息的函式來處理。這一切都被安排好了,我們照著做就可以了。

第三、功能的實現

1.最小化到托盤

建立托盤的函式ToTray

	m_tnd.cbSize = sizeof(NOTIFYICONDATA);
	m_tnd.hWnd	 = pWnd->GetSafeHwnd();
	m_tnd.uID	 = uID;
	m_tnd.hIcon  = icon;
	m_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
	m_tnd.uCallbackMessage = uCallbackMessage;
	strcpy (m_tnd.szTip, szToolTip);
	// Set the tray icon
	Shell_NotifyIcon(NIM_ADD, &m_tnd);

視窗最小化在OnSysCommand中判斷:

    else if (nID == SC_MINIMIZE)
    {
        ToTray();
	ShowWindow(SW_HIDE);//隱藏視窗
}

23功能都可以在獲得托盤事件函式處理:

LRESULT CTrayIcon::OnTrayNotification(UINT wParam, LONG lParam) 
{
	//Return quickly if its not for this tray icon
	if (wParam != m_tnd.uID)
		return 0L;

	// Clicking with right or left button brings up a context menu
	if (LOWORD(lParam) == WM_RBUTTONUP /*|| LOWORD(lParam) == WM_LBUTTONUP*/)
	{	
		//TODO:WHEN RIGHT CLICK,YOUR MENU SHOW HERE
	} 
	else if (LOWORD(lParam) == WM_LBUTTONDBLCLK) 
	{
		//TODO:DOUBLE LEFT CLICK,SHOW MAIN WINDOW
	}

	return 1;
}

4.修改圖示

這個就比較容易了,直接修改引數即可:

	m_tnd.uFlags = NIF_ICON;
	m_tnd.hIcon = hIcon;

	Shell_NotifyIcon(NIM_MODIFY, &m_tnd);

完整的例子請下載demo程式碼,借用了網上比較流行的封裝好的TrayIcon類。

參考: