|
||||
|
Программирование на Visual C++Выпуск №11 от 22/07/2000 Добрый день всем! В ответ на публикацию вопроса Дмитрия о System Tray в предыдущем выпуске помимо прямых ответов пришло еще несколько просьб рассказать о том, как в системный tray вообще помещать иконки. Я, видимо, был излишне оптимистичен, когда посчитал, что это все знают ;) Так что я решил поведать уважаемым читателям об этом в данном выпуске, в рубрике "WINAPI", в расчете на то, что эта информация будет полезна многим. Получается, сегодняшний выпуск целиком посвящен system tray ;) WINAPIИтак, задача у нас следующая: поместить в системный tray свою иконку, причем заставить ее функционировать стандартным образом – чтобы при наведении на нее появлялась подсказка, при нажатии на правую кнопку мыши выскакивало меню, на левую – производилось какое-нибудь действие. Начнем с начала – нужно поместить иконку в tray. Сами вы это вряд ли сделаете – да это и не нужно. За вас это сделает Windows, вам нужно только сообщить операционной системе о своем намерении. Для этого служит функция Shell_NotifyIcon( ), которая позволяет создавать, изменять и удалять такие иконки. Первый аргумент этой функции — это код операции, которую вам нужно осуществить. Он имеет три возможных значения — NIM_ADD, NIM_DELETE и NIM_MODIFY. В пояснениях, по-моему, не нуждается. Второй параметр – указатель на структуру NOTIFYICONDATA. Вот как эта структура выглядит: typedef struct _NOTIFYICONDATA { DWORD cbSize; // размер, обязательно указывать HWND hWnd; // HWND для посылки уведомлений UINT uID; // идентификатор иконки в tray, не имеет отношения к ресурсам UINT uFlags; // см. ниже UINT uCallbackMessage; // посылается вашей функции окна HICON hIcon; // дескриптор иконки CHAR szTip[64]; // строка с подсказкой } NOTIFYICONDATA; // uFlags #define NIF_MESSAGE 0x1 // uCallbackMessage содержит информацию #define NIF_ICON 0x2 // hIcon содержит информацию #define NIF_TIP 0x4 // szTip содержит информацию В принципе, назначение каждого члена этой структуры довольно прозрачно. Замечу только, что uID – это не идентификатор ресурса иконки, как можно было бы подумать, а вами определенный идентификатор для tray icon вашего приложения. Иконка, которую выводит в tray приложение, может меняться в процессе работы, но этот идентификатор остается постоянным. Также вам нужно в uCallbackMessage записать сообщение, которое вы хотите чтобы система вам посылала в качестве уведомления о событиях, происходящих с вашей иконкой. Для этого в программе определите какое-нибудь user-defined сообщение, например так: #define WM_TRAYNOTIFY (WM_APP+100). WM_APP используется как раз для того, чтобы именно в таком виде и определять нужные вам сообщения. Теперь, предположим у вас подготовлена иконка для tray: IDI_MYTRAYICON. Нам нужно ее вывести в tray. Вот что мы делаем: // уведомляющее сообщение #define WM_TRAYNOTIFY (WM_APP+100) // идентификатор иконки #define ID_TRAYICON 1000 … CString sNotifyTip = "Название вашей программы или другая подсказка"; NOTIFYICONDATA nid; memset(&nid, 0, sizeof(nid)); // обнулять структуру перед использованием – хорошая привычка nid.cbSize = sizeof(nid); nid.hWnd = hWnd; nid.uID = ID_TRAYICON; nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; nid.uCallbackMessage = WM_TRAYNOTIFY; nid.hIcon = ::LoadIcon(hInstance, MAKEINTRESOURCE(IDR_MAINFRAME)); lstrcpyn(nid.szTip, sNotifyTip, sizeof(nid.szTip)); Shell_NotifyIcon(NIM_ADD, &nid); Этот код вставьте в функцию инициализации, причем окно вашего приложения уже должно быть создано, hWnd и hInstance должны быть определены. hWnd вы получаете при создании окна, а hInstance вам передают прямо в WinMain. Если у вас MFC-приложение, поставьте вместо них соответственно AfxGetMainWnd()->m_hWnd и AfxGetApp()->m_hInstance. Ну вот, иконку мы вывели, и даже подсказка у нас выводится. Для своевременного удаления иконки в функцию, обрабатывающую выход из программы, поставьте примерно такую же конструкцию, но с NIM_DELETE: NOTIFYICONDATA nid; memset(&nid, 0, sizeof(nid)); nid.cbSize = sizeof(nid); nid.hWnd = hWnd; nid.uID = ID_TRAYICON; Shell_NotifyIcon(NIM_DELETE, &nid); (в структуре nid достаточно теперь определить только cbSize, hWnd и uID). Но иконка бесполезна, если она ничего не делает. Давайте добавим немного функциональности. Система посылает нам сообщение WM_TRAYNOTIFY каждый раз, когда с иконкой что-то происходит. Все, что мы должны сделать – обработать это сообщение и отреагировать должным образом. Добавьте в программу обработчик события WM_TRAYNOTIFY. В этом сообщении wParam – это ID иконки, а lParam – код сообщения от мыши, например WM_RBUTTONDOWN. Если у вас не MFC-приложение, просто добавьте один case в функцию окна. Если же вы имеете дело с MFC, то сделайте следующее: в класс главного окна(диалога) добавьте функцию afxmsg void OnTrayNotify(WPARAM wParam, LPARAM lParam); В карту сообщений класса добавьте следующую строку: ON_MESSAGE(WM_TRAYNOTIFY, OnTrayNotify) Таким образом обрабатываются пользовательские сообщения. Эта строка свяжет наше сообщение WM_TRAYNOTIFY с функцией его обработки OnTrayNotify(). В этой функции проверяйте значение lParam и делайте то, что вам нужно, например, выводите меню. Как именно это делать – уже совсем другая история… void CMyDlg::OnTrayNotify(WPARAM wParam, LPARAM lParam) { if (lParam==WM_LBUTTONDOWN) { ::SetForegroundWindow(m_hWnd); // активизируем наше приложение AfxMessageBox("Была нажата левая кнопка"); } else if (lParam==WM_RBUTTONDOWN) { ::SetForegroundWindow(m_hWnd); AfxMessageBox("Была нажата правая кнопка"); } }ВОПРОС-ОТВЕТ
Я попробовал так сделать – не получилось. У меня в этом разделе вообще всего один параметр – "Locale". Что-то автор напутал… Может, путь указан неправильно? Хоть результат и отрицательный, я решил все же на всякий случай опубликовать этот ответ – может, тут действительно дело во мне (я проверял в Windows 98SE), ведь на ListSOFT действительно была такая публикация. А может, кто и подскажет, в чем дело.
Пример я посмотрел, он работает. Но, к сожалению, у такого подхода есть один очень существенный недостаток: если TaskBar в высоту имеет больше одной полосы, никто не гарантирует, что у вас не произойдет переноса на самом неподходящем для этого символе. Я сам смоделировал такую ситуацию, это было сделать легко и выглядело совершенно неприемлемо. Если кто-нибудь знает вдруг, как эту дилемму разрешить – пишите. А насчет C# – вынужден повториться, он не позиционируется как конкурент VC и MFC. Microsoft полагает, что это Java-киллер. Так, в следующую версии VisualStudio известный продукт Visual J++, скорее всего, не войдет, а вместо него будет сами догадайтесь что… Успехов! (©Алекс Jenter mailto:jenter@mail.ru) (Красноярск, 2000.) |
|
||
Главная | В избранное | Наш E-MAIL | Прислать материал | Нашёл ошибку | Наверх |
||||
|