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;
}
</pre>
<pre>
//обработчик кнопки меню "свернуть в трей" (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,
		//сообщение, посылаемое иконкой из трея (сейчас == WM_COMMAND)
		e_tray_MSG,
		//иконка из ресурсов
		::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);
}