托盤圖標、氣泡以及任務欄崩潰後的自動添加——Shell_NotifyIcon

托盤圖標使用函數 Shell_NotifyIcon 建立、修改和刪除,參數主要使用 NOTIFYICONDATA 結構。windows

任務欄啓動時會給全部頂層窗口發送 TaskbarCreated 消息,因爲不一樣系統消息標識不同,因此須要使用 RegisterWindowMessage 向系統獲取消息標識。ide

程序在VS2015 Win32編譯經過,XP SP3測試經過。Win10氣泡無反應,或者我該用 NOTIFYICON_VERSION_4 ?但願哪位能告知一二……函數

最後發現Win10須要打開操做中心,而且容許應用通知,Win10已把氣泡消息整合到裏面去了。可憐偶調試了三天……測試

下面是簡介和本人被坑過的地方,其餘可查看VS自帶幫助。ui

1、定義:(概覽\(^o^)/)spa

BOOL Shell_NotifyIcon(
  _In_ DWORD           dwMessage,
  _In_ PNOTIFYICONDATA lpdata
);

其中 dwMessage 經常使用的選項以下:(其餘略\(^o^)/).net

NIM_ADD

 添加托盤圖標。指針

NIM_MODIFY

 修改圖標,也可彈出氣泡圖標。調試

NIM_DELETE

 刪除圖標,應在整個程序結束時也調用一次。code

第二個參數爲指向 NOTIFYICONDATA 的指針,經常使用參數以下:(其餘再略\(^o^)/)

 cbSize 

 NOTIFYICONDATA 佔用的空間大小,要注意必定要先判斷 Shell32.dll 版本號(除非你不想用於多個版本的系統),來對其賦值,具體見例程。

 hWnd 

 窗口句柄。

 uID 

 建立的圖標標識,與 hWnd 組合定位托盤圖標。

 hIcon 

 圖標句柄,通常使用 LoadIcon(hInst, MAKEINTRESOURCE(IDI_WIN32TEST)) 賦予。

 uVersion 

 版本,Win2000後通常使用 NOTIFYICON_VERSION 保證兼容性,注意它與 uTimeout 共享內存(union), NOTIFYICON_VERSION_4 適用於Vista之後的系統。

 uTimeout 

 氣泡自動消失的時間,Vista無效(VC2015幫助原文:【This member is deprecated as of Windows Vista. Notification display times are now based on system accessibility settings.】,我之前在Win7+VS2008測試時有效,因此不肯定Win7以上是否無效)

 uCallbackMessage 

托盤圖標
響應消息

當 uVersion = NOTIFYICON_VERSION :wParam爲圖標 uID lParam爲具體事件(如 WM_LBUTTONDOWN )。
當 uVersion = NOTIFYICON_VERSION_4 : HIWORD(lParam) 爲圖標 uID (16位), LOWORD(lParam) 爲具體事件, GET_X_LPARAM(wParam) 、 GET_Y_LPARAM(wParam) 爲事件響應時的座標。
 uFlags 

 標識,指出有效的成員而且指出托盤圖標顯示的方式, NIF_MESSAGE 使 uCallbackMessage 有效, NIF_ICON 使 hIcon 有效, NIF_TIP 使 szTip 有效, NIF_INFO 使 szInfo 、 szInfoTitle 、 dwInfoFlags 、 uTimeout 有效。

 szTip 

 鼠標指向托盤圖標時顯示的提示消息,注意長度。

 szInfo 

 氣泡提示內容,注意長度。

 szInfoTitle 

 氣泡標題,爲空時 dwInfoFlags 無效,注意長度。

 dwInfoFlags 

 氣泡圖標,NIIF_NONE 表示無圖標,NIIF_INFO 表示【提示】,NIIF_WARNING 表示【警告】,NIIF_ERROR 表示【錯誤】。(其餘略\(^o^)/)

 

 

2、例程:(仍是概覽\(^o^)/)

頭文件

class CTrayIcon
{
public:
	CTrayIcon();
	~CTrayIcon();

	BOOL CreateTray(HWND, HICON, UINT, LPCTSTR = _T(""));
	BOOL ChangeTray(LPCTSTR, UINT = 3000);
	BOOL DeleteTray();

private:
	ULONGLONG GetVersion(LPCTSTR);
	DWORD GetSize_NotifyIconData();
	
	NOTIFYICONDATA m_Notify;
};

獲取cbsize,這裏要特別注意,具體可參考關於NOTIFYICONDATA的一些新特性正確使用DllGetVersion

ULONGLONG CTrayIcon::GetVersion(LPCTSTR lpszDllName)
{
	HINSTANCE hinstDll;
	ULONGLONG dwVersion = 0;

	hinstDll = LoadLibrary(lpszDllName);

	if (hinstDll)
	{
		DLLGETVERSIONPROC pDllGetVersion;
		pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hinstDll, "DllGetVersion");

		if (pDllGetVersion)
		{
			DLLVERSIONINFO dvi;
			HRESULT hr;

			ZeroMemory(&dvi, sizeof(dvi));
			dvi.cbSize = sizeof(dvi);

			hr = (*pDllGetVersion)(&dvi);

			if (SUCCEEDED(hr))
			{
				dwVersion = MAKEDLLVERULL(dvi.dwMajorVersion, dvi.dwMinorVersion,
					dvi.dwBuildNumber, dvi.dwPlatformID);
			}
		}
		FreeLibrary(hinstDll);
	}
	return dwVersion;
}

DWORD CTrayIcon::GetSize_NotifyIconData()
{
	TCHAR lpszDllName[128];

	GetWindowsDirectory(lpszDllName, _TRUNCATE);
	_tcsncat_s(lpszDllName, _T("\\System32\\Shell32.dll"), _TRUNCATE);

	ULONGLONG NIDdllVer = GetVersion(lpszDllName);

	// before windows 2000
	if (NIDdllVer < MAKEDLLVERULL(5, 0, 0, 0)) {
		return NOTIFYICONDATA_V1_SIZE;
	}
	// Windows 2000
	else if (NIDdllVer < MAKEDLLVERULL(6, 0, 0, 0)) {
		return NOTIFYICONDATA_V2_SIZE;
	}
	// Windows XP or 2003
	else if (NIDdllVer < MAKEDLLVERULL(6, 0, 6000, 0)) {
		return NOTIFYICONDATA_V3_SIZE;
	}
	// Windows Vista and later
	else {
		return sizeof(NOTIFYICONDATA);
	}
}

建立:

BOOL CTrayIcon::CreateTray(HWND hWnd, HICON hIcon, UINT uCallbackMessage, LPCTSTR szTitle)
{
	m_Notify.cbSize = GetSize_NotifyIconData();
	m_Notify.hIcon = hIcon;
	m_Notify.hWnd = hWnd;
	m_Notify.uCallbackMessage = uCallbackMessage;
	m_Notify.uVersion = NOTIFYICON_VERSION;
	m_Notify.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
	m_Notify.uID = 1;

	_tcscpy_s(m_Notify.szTip, szTitle);

	return Shell_NotifyIcon(NIM_ADD, &m_Notify);
}

氣泡:

BOOL CTrayIcon::ChangeTray(LPCTSTR msg, UINT uTimeout)
{
	m_Notify.uFlags = NIF_INFO;
	m_Notify.dwInfoFlags = NIIF_NONE;
	// m_Notify.uTimeout = uTimeout;

	_tcscpy_s(m_Notify.szInfo, msg);

	return Shell_NotifyIcon(NIM_MODIFY, &m_Notify);
}

刪除:

BOOL CTrayIcon::DeleteTray() {
	return Shell_NotifyIcon(NIM_DELETE, &m_Notify);
}

定義托盤圖標響應消息:

#define WM_ICON_NOTIFY WM_USER+1001

註冊 TaskbarCreated 消息:

const UINT WM_TASKBARCREATED = ::RegisterWindowMessage(_T("TaskbarCreated"));

消息處理&調用(Win32):

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	// Restore the tray-icon after the explorer's recreation
	if (message == WM_TASKBARCREATED) {
		if (!IsWindowVisible(hWnd))
			trayIcon.CreateTray(hWnd, LoadIcon(hInst, MAKEINTRESOURCE(IDI_WIN32TEST)), WM_ICON_NOTIFY, szTitle);
		return DefWindowProc(hWnd, message, wParam, lParam);
	}

    switch (message)
	{
	case WM_SIZE:
		switch (wParam)
		{
		case SIZE_RESTORED: // Restore the window and delete the tray-icon
			ShowWindow(hWnd, SW_SHOW);
			trayIcon.DeleteTray();
			break;
		case SIZE_MINIMIZED: // Hide the window and create the tray-icon
			ShowWindow(hWnd, SW_HIDE);
			trayIcon.CreateTray(hWnd, LoadIcon(hInst, MAKEINTRESOURCE(IDI_WIN32TEST)), WM_ICON_NOTIFY, szTitle);
			break;
		default:
			break;
		}
		return DefWindowProc(hWnd, message, wParam, lParam);

    case WM_COMMAND:
        // ...
        break;
    case WM_PAINT:
		// ...
		break;
	case WM_ICON_NOTIFY:
		switch (lParam)
		{
		case WM_LBUTTONDOWN:
			SendMessage(hWnd, WM_SYSCOMMAND, SC_RESTORE, lParam);
			SetForegroundWindow(hWnd);
			break;
		default:
			break;
		}
		break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}
相關文章
相關標籤/搜索