Убрать приложение в SystemTray
Я знаю, что по этому вопросу куча инфы в инете, но времени нет. Помогите плиз.
Большая просьба. Нет времени искать в инете. Дайте плиз код, убирающий приложение в системтрэй и разворачивающий его по команде всплывающего меню.
Я знаю, что по этому вопросу куча инфы в инете, но времени нет. Помогите плиз.
Ну нахал :) а у нас значит времени навалом...
Ну да ладно лови описание (уже и не помню откуда взял) :D
Нет такого понятия "свернуть в трей". Есть возможность только добавлять, удалять и менять значок в области трея. Сама же программа просто прячется и/или минимизируется.
Для изменения значка в трее используется класс TShellNotifyIcon модуля ShellApi
Объявим следующую процедруру:
Параметры к ней такие: n - номер операции ( 1 - добавить, 2 - удалить, 3 - заменить) и Icon - сама иконка с которой будет делаться эта операция
Procedure TForm1.Ic(n:Integer;Icon:TIcon);
Var Nim:TNotifyIconData;
begin
With Nim do
Begin
cbSize:=SizeOf(Nim);
Wnd:=Form1.Handle;
uID:=1;
uFlags:=NIF_ICON or NIF_MESSAGE or NIF_TIP;
hicon:=Icon.Handle;
uCallbackMessage:=wm_user+1;
szTip:='Хинт, который будет появляться у значка';
End;
Case n OF
1: Shell_NotifyIcon(Nim_Add,@Nim);
2: Shell_NotifyIcon(Nim_Delete,@Nim);
3: Shell_NotifyIcon(Nim_Modify,@Nim);
End;
end;
Теперь, нам нужно отловить минимизацию приложения, для того, чтобы заменить стандартное действие Windows на "свёртывание в трей". Объявляем в секции protected процедуру
protected
Procedure ControlWindow(Var Msg:TMessage); message WM_SYSCOMMAND;
...
Procedure TForm1.ControlWindow(Var Msg:TMessage);
Begin
IF Msg.WParam=SC_MINIMIZE then
Begin
Ic(1,Application.Icon); // Добавляем значок в трей
ShowWindow(Handle,SW_HIDE); // Скрываем программу
ShowWindow(Application.Handle,SW_HIDE); // Скрываем кнопку с TaskBar'а
End else inherited;
End;
Итак, теперь наш обработчик ловит сообщение о минимизации и прячет нашу прогу в трей. Однако ловит не всегда. Попробуем, например, выбрать из системного меню команду Minimize или нажать на кнопку окна в панели задач, и что же? Не срабатывает!
Поэтому, нам нужно ещё переопределить обработчик onMinimize класса TApplication:
Procedure TForm1.OnMinimizeProc(Sender:TObject);
Begin
PostMessage(Handle,WM_SYSCOMMAND,SC_MINIMIZE,0);
End;
и не забудем присвоить эту процедуру:
Procedure TForm1.Form1Create(Sender:TObject);
Begin
Application.onMinimize:=OnMinimizeProc;
End;
Теперь поясню как работает. Когда приложение минимизируется, но эта минимизация не перехватывается нашим обработчиком WM_SYSCOMMAND, мы перехватываем минимизацию в процедуре OnMinimizeProc и принудительно передаём сообщение о минимизации нашей форме, где оно и будет успешно отловлено нашим обработчиком сообщения WM_SYSCOMMAND, благодаря которому прога и "сворачивается" успешно в трей и в этом случае.
Теперь нам нужно, чтобы значок в трее мог реагировать на манипуляции с ним. Если Вы внимательно посмотрите процедру Ic(), то Вы увидите там ссылку на сообщение WM_USER+1. Это не что иное, как сообщение, которое приходит нам от этого значка. Обычно для значка в трее делают всплывающее меню и выводят там те или иные действия. Но TPopUpMenu делается обычно для правой кнопки, по левой же просто активируют приложение. На форму кидаем комопонент TPopUpMenu (пусть это будет PopUpMenu1) и заносим в него все пункты меню, которые мы хотим, чтобы онм появилис в меню, которое будет всплывать по нажатию правой кнопки на значке.
После этого описываем обработчик: В вышеназванную секцию protected добавляем ещё одну процедуру IconMouse, которая будет реагировать на сообщение WM_USER+1
protected
Procedure ControlWindow(Var Msg:TMessage); message WM_SYSCOMMAND;
Pocedure IconMouse(var Msg:TMessage); message WM_USER+1;
Теперь описываем собственно процедуру.
procedure TForm1.IconMouse(var Msg:TMessage);
Var p:tpoint;
begin
GetCursorPos(p); // Запоминаем координаты курсора мыши
Case Msg.LParam OF // Проверяем какая кнопка была нажата
WM_LBUTTONUP,WM_LBUTTONDBLCLK: {Действия, выполняемый по одинарному или двойному щелчку левой кнопки мыши на значке. В нашем случае это просто активация приложения} Begin
Ic(2,Application.Icon); // Удаляем значок из трея
ShowWindow(Application.Handle,SW_SHOW); // Восстанавливаем кнопку программы
ShowWindow(Handle,SW_SHOW); // Восстанавливаем окно программы
End;
WM_RBUTTONUP: {Действия, выполняемый по одинарному щелчку правой кнопки мыши}
Begin
SetForegroundWindow(Handle); // Восстанавливаем программу в качестве переднего окна
PopupMenu1.Popup(p.X,p.Y); // Заставляем всплыть тот самый TPopUp о котором я говорил чуть раньше
PostMessage(Handle,WM_NULL,0,0) // Обнуляем сообщение
end;
End;
end;
Для выполнения пунктов всплывающего меню, пишите стандартные обработчики onClick() для его пунктов.
Данный опус писался только в форме, в IDE не тестировался, но работоспособный на 100%. Всё работает конечно, но не обессудьте, если будут ошибочки мелкие.
Большая просьба. Нет времени искать в инете. Дайте плиз код, убирающий приложение в системтрэй и разворачивающий его по команде всплывающего меню.
Я знаю, что по этому вопросу куча инфы в инете, но времени нет. Помогите плиз.
Я делаю так. На закладке Samples беру компонент TrayIcon и кладу на форму. Далее кладу PopupMenu и ImageList, в последний подгружаю иконки, и цепляю эти два компанента к, соответсственно, TrayIcon->PopupMenu и TrayIcon->Icons. Выставляю TrayIcon->IconIndex, TrayIcon->PopupMenuOn (когда позазывать всплывающее меню) и TrayIcon->RestoreOn (когда восстановить окно).
Скрываю форму методом Hide() (сопровождая методом Update(), если не помогло), восстанавливаю методом Show().
Если надо скрыть Main Form при старте, то использую событие формы OnPaint. При выходе (OnCloseQuery главной формы) скрываю иконку в трее TrayIcon->Hide = true
Можно ещё заставить его менять иконки из ImageList'a: ставим TrayIcon->Animate = true и интервал TrayIcon->AnimateInterval какой надо.
Вот и всё... если ничего не забыл :)
А вообще есть примеры с 2-мя способами создания и использования иконки в трее:
$(BCB)\Examples\Apps\TrayIcon\ и
$(BCB)\Examples\Controls\Traydemo\
Удачи!
HexoGenus, мы про Билдер или про ТрубоПаскакаль?:D
HexoGenus, мы про Билдер или про ТрубоПаскакаль?:D
А какая пофиг разница???
А если серьезно то он написал что ему срочно...
Вариант под рукой был описан для дельфей...
Я себе в копилочку складываю варианты на любом языке, была бы надежда что может работать...
... и кстати там важнее команды WinAPI ...
И че это я разошелся :)
Ладно учту на будущее...
Буду стараться приводить примеры на Билдере :D
А какая пофиг разница???
А если серьезно то он написал что ему срочно...
Вариант под рукой был описан для дельфей...
Я себе в копилочку складываю варианты на любом языке, была бы надежда что может работать...
... и кстати там важнее команды WinAPI ...
И че это я разошелся :)
Ладно учту на будущее...
Буду стараться приводить примеры на Билдере :D
Там и правда без разницы. Перевести с дельфи на билдер - нет проблем.
Там и правда без разницы. Перевести с дельфи на билдер - нет проблем.
Чего вы всполошились в самом деле... Я все это понимаю. Я ж так... позубоскалить :D