Богдан Минич дата публикации 09-07-2002 14:09 Как появляются иконки в трее.
Иконку в трей помещают с помощью Shell_NotifyIconW. Интересено посмотреть на этот процесс с
другой точки зрения.
Цитата с сайта delphi.mastak.ru:
Shell_NotifyIconW просто ищет окно с классом "Shell_TrayWnd" и посылает в него
сообщение WM_COPYDATA. в качестве данных выступает простая структура TNIDMessage.
возвращаясь к топику: если создать свое окно с классом "Shell_TrayWnd" и обрабатывать
входящие сообщения WM_COPYDATA, то можно написать полный аналог system tray! ...
(с) paul_shmakov
...чем и займемся.
В первую очередь немаловажное замечание: сообщение посылается только одному окну, то
есть наше приложение должно грузится первым. Разные там explorer'ы и другие подобные
будут мешать.
- Шаг первый:
Создаем окно "Shell_TrayWnd"
procedure TForm1.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.WinClassName := 'Shell_TrayWnd';
end; | |
Все. Окно класса "Shell_TrayWnd" имеем.
- Шаг второй:
Ловим WM_COPYDATA
procedure TFORM1.WMCOPYDATA(var Msg: Tmessage);
var
pcd: PCopyDataStruct;
NID: PNotifyIconData;
begin
pcd := PCOPYDATASTRUCT(msg.lParam);
if pcd^.dwData = 1 then begin
NID := pointer(integer(pcd.lpData)+8);
case integer(pointer(integer(pcd.lpData)+4)^) of
NIM_ADD: Msg.Result := NewTrayIcon(NID); // добавить иконку
NIM_DELETE: Msg.Result := DeleteTrayIcon(NID); // удалить иконку
NIM_MODIFY: Msg.Result := ModifyTrayIcon(NID); // изменить иконку (или подсказку)
end;
exit;
end;
end; | |
Обратите внимание на Msg.Result. Желательно чтобы NewTrayIcon, DeleteTrayIcon,
ModifyTrayIcon возвращали Integer(True) или Integer(False) в зависимости от
помещения/удаления иконки.
Некоторые приложения не проверяют этот результат, но если начнут проверять - то
причины "глючного" поведения иконки того же AVP Monitor можно искать долго и
безуспешно.
- Шаг третий:
Поймали, и че с ним теперь делать?
А мы имеем очень интересную структуру -
- NID.cbSize - размер записи, в принципе не интересен;
- NID.Wnd - хендл окна (владельца иконки);
- NID.uID - идентификатор иконки (если их в приложении несколько), для данной задачи нужен для отсылки обратного сообщения;
- NID.uFlags - определяет, какие поля используются в сообщении. Параметр может быть любой комбинацией из флагов (0 - uCallbackMessage, 2 - hIcon, 4 - czTip);
- NID.uCallbackMessage - номер сообщения, которое посылается окну, определяемому полем NID.Wnd (владельцу). lParam отсылаемого сообщения дожен равняться NID.uID, а wParam сообщение от мыши.
Пример: PostMessage(NID.Wnd, NID.uCallBack, NID.uID, MOUSE_EVENT) где MOUSE_EVENT может принимать значения WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBLCLK и подобные для других кнопок мыши.
- NID.hIcon - хендл иконки, которую собственно и предполагается отображать;
- NID.szTip - строка, оканчивающаяся нулевым символом, содержит подсказку, которая должна выводится при наведении курсора на иконку.
-
В случаях ошибки нужно информировать приложения про необходимость
поместить иконки обратно. Для этого послужат такие действия:
procedure TForm1.FormCreate(Sender: TObject);
var
WM_TASKBARCREATED: UINT;
begin
WM_TASKBARCREATED := RegisterWindowMessage('TaskbarCreated');
PostMessage(HWND_BROADCAST, WM_TASKBARCREATED, 0, 0);
end; | |
Не все приложения реагируют на такое сообщение.
Скачать демо проект DemoTray.zip (9.8K)
И несколько слов о демо проекте.
ВНИМАНИЕ!!! Следуйте данным инструкциям только в том случае, если Вы
ясно понимаете смысл действий!!!
Повторюсь: Shell_NotifyIconW сообщение посылает только одному окну.
Поэтому чтобы увидеть результаты работы демопроекта, загружать его
надо без или вместо explorer'а.
Первый вариант (для Win9x):
Пример: файл %windir%\system.ini изменить следующим образом:
Найти строчку:
shell=explorer.exe
Заменить на (предполагается что демопроект находится в C:\Demotray\ ) :
;shell=explorer.exe
shell=c:\demotray\demotray.exe
Перегрузите Windows
Для возврата explorer'a раскомментируйте первую строчку,
закомментируйте или удалите вторую.
Второй вариант: Лично я использую Far для выгрузки Explorer.exe
- 1) Загружаем IDE Delphi и демопроект
- 2) Загружаем Far, F11->Process list->
выбираем EXPLORER.EXE->F8->OK
- 3) Отлаживаем проект
- 4) Для появления Explorer'a просто запустите его.
Используйте эти инструкции на свой страх и риск. Прочитайте их дважды.
Внимательно изучите исходники. Трижды.
Инструкции по закрытию EXPLORER.EXE действительны для Win9x.
Если у Вас NT - разберитесь сами. Если не сможете разобратся - то за
такие проекты Вам браться рановато.
Гревные ругательства "А у меня после ... ничего не работает!" не
принимаются.
Благодарности:
- Paul Shmakov - реверсинг Shell_NotifyIcon, моральная поддержка.
- Стив Тейксейра & Ксавье Пачеко - литература.
- Особая благодарность обоим использованым алфавитам.
Богдан Минич
[Systray] [Shell Extensions]
Обсуждение материала [ 10-10-2007 06:28 ] 12 сообщений |