На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Rouse_, jack128, Krid
  
    > "Свернуть" программу в трей , Как добавить значок программы в трей?
      Нет такого понятия "свернуть в трей". Есть возможность только добавлять, удалять и менять значок в области трея. Сама же программа просто прячется и/или минимизируется.
      Для работы со значками в трее используется функция Shell_NotifyIcon, объявленная в модуле ShellApi.

      Объявим следующую процедруру:
      Параметры к ней такие: n - номер операции ( 1 - добавить, 2 - удалить, 3 - заменить) и Icon - сама иконка с которой будет делаться эта операция

      ExpandedWrap disabled
        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 процедуру

      ExpandedWrap disabled
        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:

      ExpandedWrap disabled
        Procedure TForm1.OnMinimizeProc(Sender:TObject);
        Begin
         PostMessage(Handle,WM_SYSCOMMAND,SC_MINIMIZE,0);
        End;


      и не забудем присвоить эту процедуру:

      ExpandedWrap disabled
        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

      ExpandedWrap disabled
        protected
         Procedure ControlWindow(Var Msg:TMessage); message WM_SYSCOMMAND;
         Procedure IconMouse(var Msg:TMessage); message WM_USER+1;


      Теперь описываем собственно процедуру.
      ExpandedWrap disabled
        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%. :) Всё работает конечно, но не обессудьте, если будут ошибочки мелкие.
      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
      0 пользователей:


      Рейтинг@Mail.ru
      [ Script execution time: 0,0255 ]   [ 16 queries used ]   [ Generated: 18.04.24, 20:13 GMT ]