Во многих форумах с завидной систематичностью выплывают вопросы об иконках
в трее и многие программеры с недовольством отвечают:
"Это же так просто... почитай документацию." Но если я к примеру по
Англицки не разумею, то и документация мне не очень поможет...
Эта же статья предназначена для заполнения некоторого "информационного вакуума"
сложившегося по данной теме и раскажет
о некоторых приемах работы с треем в Delphi.
Определения
рис.1
Итак Tray (рис.1) - это область рабочего стола Explorer'а которая находится
в одном из углов экрана "там где часы"(в зависимости от положения панели
инструментов. Вся информация которую можно из него
"почерпнуть" содержится в виде пиктограмм и всплывающих подсказок.
С чего начать
Для операций с иконками в трее используется только одна функция
Windows - Shell_NotifyIconData определение которой "звучит" следующим образом: function Shell_NotifyIcon(dwMessage: DWORD; lpData: PNotifyIconData): BOOL; stdcall;
И в качестве параметров принимает следующие значения:
dwMessage
- идентификатор сообщения которое посылается иконке
в трее. Может принимать следующие значения:NIM_ADD,NIM_DELETE,NIM_MODIFY
lpData
- указатель на структуру TNotifyIconData, в которой
помещена информация о параметрах иконки.
Возвращаемое значение
- принимает True при успешном завершении
операции или False в противном случае.
Как видно сам синтаксис функции не сказал нам ничего нового о том, как реализована работа с Треем. Эта функция только изменяет состояние иконки в зависимости от значения параметра dwMessage, а єто значит что вся нужная нам информация находится в структуре TNotifyIconData. Давайте теперь рассмотрим ее более детально...
Структура TNotifyIconData
cbSize
DWORD
Wnd
HWND
uID
UINT
uFlags
UINT
uCallbackMessage
UINT
icon
HICON
szTip
array[0..64] of AsiChar
Описание параметров:
cbSize
- как и одноименные параметры из тругих системных
структур задает размер структуры TNotifyIconData.
Wnd
- идентификатор окна, которое будет реагировать на
сообщения нашей иконки.
UID
- идентификатор, по которому Wnd определяет нашу иконку.
uFlags
- флаги,которые могут принимать значения: NIF_ICON,NIF_MESSAGE,
NIF_TIP.
Icon
- идентификатор иконки, которая будет размещена в трее
szTip
- строка всплывающей подсказки.
Tray в чистом виде
А теперь приступим к собственно выводу иконки в трей.
Для начала создадим форму в которой все это разместим.
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
procedure TrayDefaultHandler(var Message:TMessage);
{ Private declarations }
public
Data:TNotifyIconData;
{ Public declarations }
end;
Потом кнопку TButton, в которой запишем:
procedure TForm1.Button1Click(Sender: TObject);
var H:THandle;
begin
H:=AllocateHWnd(TrayHandler);
FillChar(S,SizeOf(S),#0);
Data.cbSize:=SizeOf(S);
Data.Wnd:=H;
Data.uCallbackMessage:=WM_TRAYICON;
Data.uFlags:=NIF_ICON or NIF_TIP or NIF_MESSAGE;
Data.hIcon:=Application.Icon.Handle;
StrPCopy(data.szTip,Application.Title);
Shell_NotifyIcon(NIM_ADD,@data);
end;
Небольшие пояснения. Во первых - мы создаем постое окно с дескриптором H,
которое будет реагировать на сообщения иконки. После этого мы очищаем
предопределенную структуру Data типа TNotifyIconData, затем заполням
необходимые поля. Значение поля uFlags - представляют собой уведомление
системы о том, что ей надо использовать. Так использование значения NIF_ICON
уведомляет систему о том, что в поле hIcon присутствует непустое значение,
которое надо вывести в виде иконки, NIF_TIP - говорит о наявности текста
всплывающей подсказки в поле szTip, а значение NIF_MESSAGE - о том,
что в поле Wnd присутствует дескриптор окна, которому передается управление
при возникновении того или иного сообщения у иконки.
После заполнения всех необходимых полей вызывается функция Shell_NotifyIcon
со значением NIM_ADD - добавление иконки в трей.
Теперь рассмотрим реакцию иконки на сообщения:
procedure TForm1.TrayDefaultHandler(var Message:TMessage);
begin
if Message.Msg=WM_TRAYICON then
if Message.LParam=WM_LBUTTONDOWN then
begin
ShowMessage('Left Button Down');
end;
end;
как видно из текста - здесь в качестве реакции реализован простой вывод
уведомления о нажатии левой кнопки мыши на иконке. Идентификатор WM_TRAYICON -
который используется здесь определен нами в модуле главной формы следующим образом:
const WM_TRAYICON = WM_USER + 1;
такое определение необходимо для того чтобы сообщения системы не перекрывались.
После того, как мы убедились в наличии реакции и хотим закрыть приложение - нам
надо удалить нашу иконку из трея т.к. если мы этого не сделаем (а за нас это
никто не сделает), то она останется там лежать до следующей перегрузки Explorer'а.
Удаление иконки реализуется таким кодом:
procedure TForm1.FormDestroy(Sender: TObject);
begin
Shell_NotifyIcon(NIM_DELETE,@data);
end;
здесь нам даже не потребовалось никаких вмешательств в структуру data,
мы просто вызвали Shell_NotifyIcon с необходимым параметром.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
const UWM_TRAYICON = WM_USER+1;
const ID_TRAYICON = 1;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
procedure TrayDefaultHandler(var Message:TMessage);
{ Private declarations }
public
data:TNotifyIconData;
{ Public declarations }
end;
var
Form1: TForm1;
implementation
Uses ShellApi;
{$R *.dfm}
procedure TForm1.TrayDefaultHandler(var Message:TMessage);
begin
if Message.Msg=UWM_TRAYICON then
if Message.LParam=WM_LBUTTONDOWN then
begin
ShowMessage('Left Button Down');
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var H:THandle;
begin
H:=AllocateHWnd(Self.TrayDefaultHandler);
FillChar(S,SizeOf(S),#0);
data.cbSize:=SizeOf(S);
data.Wnd:=H;
data.uCallbackMessage:=UWM_TRAYICON;
data.uFlags:=NIF_ICON or NIF_TIP or NIF_MESSAGE;
data.hIcon:=Application.Icon.Handle;
StrPCopy(data.szTip,Application.Title);
Shell_NotifyIcon(NIM_ADD,@data);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Shell_NotifyIcon(NIM_DELETE,@data);
end;
end.
Заключение
Эта небольшая заметка лишь немножко приоткрывает занавес над таким полем
деятельности как иконки в трейбаре и призвана скорее "пробудить аппетит"
нежели "утолить жажду знаний" и показать направление в котором нужно
двигаться. Кроме того есть множество сайтов на которых вывешены компоненты
для работы с трейбаром от простых до многофункциональных с возможностью
анимации(как в The Bat!) и прочими "вкусностями". Но как говориться:
"НЕТ предела совершенству". Так что дерзайте.