Блог Александра Божко
Архивы
Рубрики
Поделись с другими!
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

Пост шпаргалка. Если вы обладатель Delphi XE6 или Delphi XE7, вам не нужно делать каких-то хитрых телодвижений, для того, создания кнопок на панели, соответствующей приложению в TaskBar‘е. Вы можете воспользоваться компонентом TTaskBar и, таким образом, решить все проблемы. Но, что делать, пользователям Delphi предыдущих версий (попутно напомню,  что при покупке последней версии Delphi вы получаете ключи ко всем предыдущим версиям, начиная с Delphi 7)?

У Боба Сворта есть довольно подробный солюшн, но я нашел в нем некоторые неточности. Ниже приведу свою, немного модифицированную версию данного решения.

Создание TaskbarList‘а ничем особо не отличается. Этот код будет работать и в Windows 7 и в Windows 8:

 

  procedure CreateTaskBarList();
  begin
      TaskbarList := CreateComObject(CLSID_TaskbarList) as ITaskbarList;
      TaskbarList.HrInit;
      Supports(TaskbarList, IID_ITaskbarList2, TaskbarList2);
      Supports(TaskbarList, IID_ITaskbarList3, TaskbarList3);
      Supports(TaskbarList, IID_ITaskbarList4, TaskbarList4);

    if not Application.MainFormOnTaskBar then
      FormHandle := Application.Handle
    else FormHandle := Application.MainForm.Handle;

      TaskbarList3.ThumbBarSetImageList(FormHandle, FMain.ImageList2.Handle);
  end;

Естественно, предварительно нужно проверить версию Windows (она должна быть не ниже 7). Я делаю это так же как и Dr. Bob:

  NeedCreateTBwButtons:= ((Win32MajorVersion=6) and (Win32MinorVersion>0)) or (Win32MajorVersion>6);

В надежде на то, что в последующих версиях Windows этот функционал никуда не денется. Ниже приведены значения переменных для существующих версий системы.

Win32MajorVersion Win32MinorVersion
6
  • Windows 8 (version 6.2)
  • Windows 7 (version 6.1)
  • Windows Vista (version 6.0)
5
  • Windows XP (version 5.1)
  • Windows 2000 (version 5.0)

А вот с кнопками на панели все не так просто. То, что показано в исходном примере работать будет. Но только для случая с одной кнопкой. Если внимательно почитать документацию, то в качестве параметра для метода ThumbBarAddButtons передается ссылка на массив THUMBBUTTON, а не на отдельную кнопку. Максимальное количество элементов в массиве – 7. Массив должен быть статическим.

Я описал его так:

ThbButtons: array [0..3] of TThumbButton;

Соответственно, кнопки я создаю следующим образом:

    ThbButtons[0].iId := 42;
    ThbButtons[0].iBitmap := 0;
    ThbButtons[0].dwMask := THB_FLAGS or THB_BITMAP or THB_TOOLTIP;
    ThbButtons[0].dwFlags :=  THBF_ENABLED;

    StrCopy(ThbButtons[0].szTip, PChar('Start Timer'));

    ThbButtons[1].iId := 43;
    ThbButtons[1].iBitmap := 1;

    ThbButtons[1].dwMask := THB_FLAGS or THB_BITMAP or THB_TOOLTIP;
    ThbButtons[1].dwFlags :=  THBF_ENABLED;

    StrCopy(ThbButtons[1].szTip, PChar('Pause Timer'));

    ThbButtons[2].iId := 44;
    ThbButtons[2].iBitmap := 2;

    ThbButtons[2].dwMask := THB_FLAGS or THB_BITMAP or THB_TOOLTIP;
    ThbButtons[2].dwFlags :=  THBF_ENABLED ;

    StrCopy(ThbButtons[2].szTip, PChar('Stop Timer'));

    ThbButtons[3].iId := 45;
    ThbButtons[3].iBitmap := 3;

    ThbButtons[3].dwMask := THB_FLAGS or THB_BITMAP or THB_TOOLTIP;
    ThbButtons[3].dwFlags :=  THBF_ENABLED;

    StrCopy(ThbButtons[3].szTip, PChar('Cancel'));

    TaskbarList3.ThumbBarAddButtons(FormHandle, 4, @ThbButtons);

Значения флагов, что называется “dwFlags”, не буду здесь их перечислять, для этого есть документация.

Как вы, наверное, уже догадались, здесь я реализовал кнопки  таймера. Обработчик события нажатия кнопок можно реализовать так. как и в базовом примере (отловить сообщение WM_COMMAND). В демонстрационном примере он у меня сработал, а вот в реальном приложении, – почему-то нет. Вероятно, где-то что-то перекрывается. Я не слишком огорчился сему факту, и использовал событие OnMessage компонента ApplicationEvents.

Получилось примерно так:

if (Msg.message = WM_COMMAND) then
begin

 btnNo:= LOWORD(Msg.wParam);

 case btnNo of
  42:
  begin
    PlayBtn.Click;
  end;
  43:
  begin
    PauseBtn.Click;
  end;

  44:
  begin
    StopBtn.Click;
  end;

  45:
  begin
    CancelBtn.Click;
  end;

 end;

Понятно, что в качестве параметра здесь передается не переменная типа TWMCommand, как в оригинальном примере, а переменная типа tagMsg.

  tagMSG = packed record
    hwnd: HWND;
    message: UINT;
    wParam: WPARAM;
    lParam: LPARAM;
    time: DWORD;
    pt: TPoint;
  end;

Поэтому, и приходится id кнопки вытаскивать немного по другому. В данном случае при нажатии на кнопку в панели TaskBar‘а, я нажимаю на соответствующую кнопку в приложении.

И после нажатия на кнопку требуется изменить состояние кнопок (активна/ не активна). Т. е. мы должны не только добавлять кнопки, но и изменять уже имеющиеся. Примерно так.

  procedure SetThbBtnVisible();

  function BlnToInt(aEnabled: Boolean): Integer;
  begin
     if aEnabled then
        Result:= 0
     else
        Result:= 1;
  end;

  begin
     ThbButtons[0].dwFlags :=  BlnToInt(FMain.PlayBtn.Enabled);
     ThbButtons[1].dwFlags :=  BlnToInt(FMain.PauseBtn.Enabled);
     ThbButtons[2].dwFlags :=  BlnToInt(FMain.StopBtn.Enabled);
     ThbButtons[3].dwFlags :=  BlnToInt(FMain.CancelBtn.Enabled);

     TaskbarList3.ThumbBarUpdateButtons(FormHandle, 4, @ThbButtons);
  end;

С учетом того, что флаги THBF_ENABLED и THBF_DISABLED у нас описаны следующим образом:

  THBF_ENABLED        =  $0000;
  {$EXTERNALSYM THBF_ENABLED}
  THBF_DISABLED       =  $0001;

Обновление существующих кнопок производится с помощью метода ThumbBarUpdateButtons.

Понятно, что SetThbBtnVisible нужно вызывать после каждого нажатия на кнопку таймера (как на TaskBar, так и в приложении) В итоге получаем примерно такую картинку:

DelphiTaskBarButtons

Размер иконок в ImageList лучше борать 32×32.


Поделись с другими!
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

8 комментариев: Taskbar buttons

  • Если мне память не изменяет, то начинать создание кнопок нужно после того как получено сообщение от винды, о том, что кнопка в панели задач создана.

    • Не совсем понял…

      • Note When an application displays a window, its taskbar button is created by the system. When the button is in place, the taskbar sends a TaskbarButtonCreated message to the window. Its value is computed by calling RegisterWindowMessage(L(“TaskbarButtonCreated”)). That message must be received by your application before it calls any ITaskbarList3 method.

        (с) http://msdn.microsoft.com/ru-ru/library/windows/desktop/dd378460%28v=vs.85%29.aspx

        • А, я понял о чем речь. Имеется ввиду, создана -ли сама панелька, соответствующая приложению на Таскбаре. Ну, там Боб Сворт схитрил, и я вслед за ним. Спс. Да надо, в ApplicationEvent поймать это сообщение и привязать к булевскому флажку. Тогда, в принципе, не нужно будет и версию винды проверять.

          • а при перезапуске Проводника, т.е. если убить процесс exploerer.exe и запустить его вновь, эти созданные кнопочки останутся или потребуется вновь создавать?

            если останутся то хорошо, а если вновь, то лучше регаться для получения сообщения и создавать кнопочки каждый раз при его получении.

            • Кстати, в том же WinAmp они не пересоздаются. Очевидно да. Ловить надо сообщение.

            • Немного озадачило то, что в процессе запуска приложения эта мессага приходит трижды.
              Тем не менее, если повесить код создания кнопок на событие, привязанное к этому сообщению – все работает.

  • Позволю себе оставить ссылочку на схожую тему… случайно наткнулся:
    http://delphi32.blogspot.ru/2011/05/adding-windows-7-jump-list-to-delphi.html

Оставить комментарий

Ваш email не будет опубликован. Обязательные поля отмечены *

Вы можете использовать это HTMLтеги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Продукты DevArt
Купить онлайн:



Читай русскоязычные Delphi блоги
Каталог блогов Blogdir.ru
Яндекс.Метрика