Советы по Windows (часть 6) - ОС и разработчик - Shelek
Создание иконки в области уведомлений



Все знают, как удобно, когда приложение размещает свою иконку в трее (полностью - TrayBar или, как теперь называет это Microsoft, Область Уведомлений) и поэтому не мешается на экране или в панели задач. Но работа с треем осуществляется совсем не так, как с панелью задач. Самое интересное, что, чтобы найти информацию по этому вопросу в MSDN, мне потребовалось довольно много времени. Да и удобство изложения материала оставляло желать лучшего.

Итак, начнём по порядку. Все действия с областью уведомлений производятся с помощью одной функции - Shell_NotifyIcon. Так что по имени этой функции вы сможете найти в MSDN всё, что связано с треем.
Функция объявлена так:
Код:
BOOL Shell_NotifyIcon(
DWORD dwMessage,
PNOTIFYICONDATA lpdata
);

Первый параметр определяет выполняемое действие (NIM_ADD, NIM_DELETE и т. д.), а второй - это указатель на структуру типа NOTIFYICONDATA, содержащую дополнительную информацию.

Приступим к помещению иконки в область уведомлений. Нужно заметить, что нам необходимо будет обрабатывать сообщения, приходящие от этой иконки. Но эти сообщения мы должны определить сами:
Код:
#define WM_TRAYNOTIFY WM_USER + 2

Почему WM_USER + 2? Потому что WM_USER и WM_USER + 1, вероятно, уже используется в вашей программе (это сообщения DM_GETDEFID и DM_SETDEFID соответственно). Так что на всякий случай надо принять меры предосторожности.

Идём дальше. Объявляем (лучше глобально) структуру типа NOTIFYICONDATA:
Код:
NOTIFYICONDATA tr_icon_data;

Теперь где-нибудь после создания окна и до начала цикла обработки сообщений помещаем следующий код:
Код:
//создаём значок в TrayBar
tr_icon_data.cbSize = sizeof(tr_icon_data);
tr_icon_data.hWnd = hWndMain; //HWND главного окна
tr_icon_data.uID = 0x10; //идентификатор может быть любой
//следующая строка означает, что поля hIcon, szTip и uCallbackMessage
//заполнены правильно. Остальные игнорируются.
tr_icon_data.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE;

tr_icon_data.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON1));
strcpy(tr_icon_data.szTip, "Всплывающая подсказка к нашей программе");
tr_icon_data.uCallbackMessage = WM_TRAYNOTIFY;

//теперь создаём иконку
Shell_NotifyIcon(NIM_ADD, &tr_icon_data);

Вот и всё. Если бы не одно но... Иногда это сильно подтормаживает программу. Я не знаю, что там так медленно работает, но я нашёл способ, как этого избежать. Весь последний фрагмент кода я поместил в отдельную функцию, которую вызываю в отдельном потоке. Результат мгновенный.

Итак, объявляем функцию
Код:
void WINAPI CreateNotifyIcon();

Затем помещаем в её тело вышеупомянутый фрагмент кода (т. е. заполнение структуры и вызов функции Shell_NotifyIcon). И запускаем нашу функцию как отдельный поток в том месте программы, где раньше находился всё тот же вышеупомянутый фрагмент кода:
Код:
HANDLE hThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)CreateNotifyIcon, NULL, 0, NULL);

CloseHandle(hThread);

Теперь всё. Спросите, как теперь удалить из трея эту прекрасную иконку? Всё просто - после завершения цикла обработки сообщений пишем
Код:
Shell_NotifyIcon(NIM_DELETE, &tr_icon_data);

Ну, теперь уже совсем всё. Удачи вам.

P. S. Чуть не забыл... Не пробуйте создавать элементы управления (вообще любые окна) в отдельном потоке - при завершении потока они удаляются!!!
Information
  • Posted on 01.02.2010 00:38
  • Просмотры: 1634