FAQ:WinAPI VCPP:иконка в области уведомлений (системном трее)

Материал из Весельчак У
Перейти к: навигация, поиск

Как создать иконку в области уведомлений (системном трее)? Как определить, какие действия производит с иконкой пользователь? Как сделать анимацию иконки в трее? Как удалить иконку?

Для всего этого - использовать процедуру API Shell_NotifyIcon(). Например, сделаем так, чтобы, по нажатию кнопки меню, окно программы сворачивалось в трей (иконка сначала недолго поморгает), а при щелчке левой кнопкой мыши по иконке - разворачивалось к предыдущему состоянию. В примере использовано одно документное приложение (MDI), поэтому "всё происходит" в классе CMainFrame. Переписать для CDialog и вообще для любого случая - несложно.

//определение класса CMainFrame
class CMainFrame : public CFrameWnd
{
	// переменная для сохранения состояния окна до сворачивания.
	// "Запоминаем" сюда значения SW_MAXIMIZE или SW_RESTORE
	DWORD m_dwdTrayShowCMD;
 
	// определяем константы
	enum
	{
		// идентификатор иконки приложения в трее.
		// не путать с ID ресурса иконки!!!
		e_tray_ID = 1000,	
		e_tray_ID_1 = 1001,	 //(ID второй иконки для анимации)
		e_tray_MSG = WM_COMMAND, //сообщение, посылаемое из трея
	};
 
	// это добавит визард ->
 
// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CMainFrame)
 
	protected:
	virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
	//}}AFX_VIRTUAL
};
 
//конструктор
CMainFrame::CMainFrame()
{
	m_dwdTrayShowCMD = SW_MAXIMIZE;
}
// обработчик кнопки меню "свернуть в трей" (ID_PUTTOTRAY)
void CMainFrame::OnPuttotray()
{
	// "запоминаем", какой командой потом разворачивать окно
	m_dwdTrayShowCMD = ((GetStyle() & WS_MAXIMIZE) ? SW_MAXIMIZE : SW_RESTORE);
 
	// заполняем структуру NOTIFYICONDATA для иконки
	NOTIFYICONDATA ndata =
	{
		sizeof(NOTIFYICONDATA), // размер структуры
		m_hWnd, // хендл этого окна
		e_tray_ID, // идентификатор иконки трея в приложении
		NIF_ICON | NIF_MESSAGE | NIF_TIP, // опции: есть иконка, есть сообщение, есть надпись
		e_tray_MSG, // сообщение, посылаемое иконкой из трея (сейчас == WM_COMMAND)
		::AfxGetApp()->LoadIcon(IDR_MAINFRAME), // иконка из ресурсов
		"Значок моей программы" // всплывающая надпись
	};
 
	// заполняем структуру NOTIFYICONDATA для "пустой" иконки
	NOTIFYICONDATA ndata1 = ndata;
	ndata1.hIcon = 0;
 
	// скрываем окно программы
	ShowWindow(SW_HIDE);
 
	// добавляем значок e_tray_ID в трей
	Shell_NotifyIcon(NIM_ADD, &ndata);
 
	// "моргаем" 4 раза
	for (int i = 0; i < 4; i++)
	{
		// заменяем значок в трее пустым
		Shell_NotifyIcon(NIM_MODIFY, &ndata1);
		Sleep(70);
 
		// возвращаем обратно иконку
		Shell_NotifyIcon(NIM_MODIFY, &ndata);
		Sleep(70);
	}
 
	return;
}

Добавим обработчик для команды e_tray_MSG (WM_COMMAND) - переопределим виртуальную функцию

BOOL CWnd::OnCommand(WPARAM wParam, LPARAM lParam)

BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM lParam) 
{
	// определяем, что сообщение от иконки e_tray_ID
	if (wParam == e_tray_ID)
	{
		// определяем, какое действие мышью произвели
		switch (lParam)
		{
			case WM_LBUTTONDOWN:
			{
				// показываем окно ("запомненной" командой)
				ShowWindow(m_dwdTrayShowCMD);
 
				// заполняем структуру для удаления иконки
				NOTIFYICONDATA ndata =
				{
					sizeof(NOTIFYICONDATA),
					m_hWnd,
					e_tray_ID
				};
 
				// удаляем иконку
				Shell_NotifyIcon(NIM_DELETE, &ndata);
			}
			break;
 
			case WM_MOUSEMOVE:
			{
				// по иконке двигался курсор
			}
			break;
 
			case WM_LBUTTONUP: {} break;
			case WM_LBUTTONDBLCLK: {} break;
			case WM_RBUTTONDOWN: {} break;
			case WM_RBUTTONUP: {} break;
			case WM_RBUTTONDBLCLK: {} break;
			case WM_MBUTTONDOWN: {} break;
			case WM_MBUTTONUP: {} break;
			case WM_MBUTTONDBLCLK: {} break;
		}
 
		// сообщение обработано
		return 1;
	}
 
	return CFrameWnd::OnCommand(wParam, lParam);
}