FAQ:WinAPI VCPP:иконка в области уведомлений (системном трее)
Материал из Весельчак У
Версия от 21:11, 30 июля 2008; RXL (обсуждение | вклад)
Как создать иконку в области уведомлений (системном трее)? Как определить, какие действия производит с иконкой пользователь? Как сделать анимацию иконки в трее? Как удалить иконку?
Для всего этого - использовать процедуру 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); }