Установка иконки приложения в system tray
Поговорим о сожительстве трея (SysTray, где часики и всякие иконки у Вас в Windows-е живут) и Delphi. А именно - как засунуть иконку в трей своими руками и не запачкаться.
Зачем помещать иконку в трей? Очевидно, таким образом TaskBar меньше засоряется и программы работающие в background меньше мозолят глаза оставаясь по прежнему лёгко-доступными. К сожалению, в дистрибутивах Delphi нет компоненты, позволяющей легко и не принудительно помещать иконки в трей (возможно будет, так как компонента TrayIcon есть в C# Builder). По этой причине предлагаю не искать по всему интернету готовое решение, а сделать всё самому. На самом деле всё просто.
Нам понадобится системная функция Shell_NotifyIcon. Чтобы иметь к ней доступ необходимо подключить библиотеку ShellAPI (uses ShellAPI;). Синтаксис Shell_NotifyIcon:
-
Shell_NotifyIcon(dwMessage: integer; pnid: PNOTIFYICONDATA): boolean;
dwMessage указывает на осуществляемую операцию и может принимать значения NIM_ADD - добавить иконку, NIM_DELETE - удалить существующую иконку и NIM_MODIFY - изменить. Результат функции опредеяется успешностью проведённой операции. pnid - это структура с описанием создаваемой иконки.
Чтобы создать нашу первую иконку напишем следующий код в разделе interface:
-
Const WM_ICONTRAY = WM_USER + 1;
-
// Это сообщение будет передаваться от иконки в программу
-
-
Type TForm1 = class(TForm)
-
private
-
{ Private declarations }
-
TrayIconData: TNotifyIconData;
-
public
-
{ Public declarations }
-
end;
Теперь добавим PopupMenu в наш проект и создадим обработчики OnCreate и OnDestroy для нашей формы. Ниже приведён код OnCreate, создающий во время запуска нашего проекта необходимую иконку:
-
procedure TForm1.FormCreate(Sender: TObject);
-
begin
-
with TrayIconData do
-
begin
-
cbSize := SizeOf(TrayIconData);
-
// Размер используемой структуры
-
Wnd := Handle;
-
// Дескриптор окна, получающего сообщения
-
uID := 0;
-
// Идентификатор иконки для программы,
-
// используется для работы с несколькими иконками
-
uFlags := NIF_MESSAGE + NIF_ICON + NIF_TIP;
-
// Иконка передаёт сообщения в программу, имеет изображение и подсказку
-
uCallbackMessage := WM_ICONTRAY;
-
// Иконка передаёт сообщение WM_ICONTRAY
-
hIcon := Application.Icon.Handle;
-
// Дескриптор изображения для иконки
-
StrPCopy(szTip, Application.Title);
-
// szTip содержит подсказку
-
end;
-
Shell_NotifyIcon(NIM_ADD, @TrayIconData);
-
// Создаём иконку в трее
-
end;
Вроде больше нечего дополнить. Если необходимо создать дополнительные иконки, то необходимо для каждой их них назначать уникальное значение uID. При закрытии программы следует убрать созданную иконку из трея:
-
procedure TForm1.FormDestroy(Sender: TObject);
-
begin
-
Shell_NotifyIcon(NIM_DELETE, @TrayIconData);
-
end;
В функции мы передаём @TrayIconData, а не TrayIconData, так как функции требуют тип PNotifyIconData - указатель на структуру. Чтобы обрабатывать передаваемое в программу сообщение от иконки необходимо написать функцию обработки сообщения WM_ICONTRAY. Для этого в описание TForm1 добавим строку
-
procedure TrayMessage(var Msg: TMessage); message WM_ICONTRAY;
и напишем соответствующую процедуру:
-
procedure TForm1.TrayMessage(var Msg: TMessage);
-
begin
-
case Msg.lParam of
-
WM_LBUTTONUP:
-
// Произошло нажатие на левую кнопку,
-
// прячем или показываем главное окно программы
-
begin
-
if Form1.Visible then
-
Form1.Hide
-
else
-
Form1.Show
-
end;
-
WM_RBUTTONUP:
-
// Произошло нажатие на правую кнопку
-
begin
-
SetForegroundWindow(Handle);
-
PopupMenu1.Popup(Mouse.CursorPos.X, Mouse.CursorPos.Y);
-
// Показываем всплывающее меню (помните, мы его создали в самом начале)
-
PostMessage(Handle, WM_NULL, 0, 0);
-
// В Windows есть баг, поэтому чтобы не было проблем с менюшкой
-
// Microsoft рекомендует делать такой вызов
-
end;
-
end;
-
end;
Вот и всё, иконка готова. Что можно добавить? Например, таймер, чтобы сделать анимированную иконку, можно разукрасить менюшку. Вобщем фантазия ни чем не ограничена :)


March 6th, 2007 at 13:05 Quote
Кхм, а почему не указано оригинальное авторство? Это новый прикол такой?
March 6th, 2007 at 13:09 Quote
статья была написана тобой для Erased.info, который принадлежит мне. и я счел возможным продублировать статью тут в таком виде, в каком мне было удобно. кроме того, авторство тут относится разве что к связующим фразам между кодом.
April 4th, 2008 at 15:21 Quote
Спасибо, чайнику помогло. Все просто и ясно даже мне
July 16th, 2008 at 13:29 Quote
2 Filosoff:
Авторское право ещё никто не отменял. Даже если вы и владеете имущественными правами на данную статью.
October 15th, 2008 at 11:49 Quote
супер, большое спасибо