Delphi programming blog
Источник: http://teran.karelia.pro/articles/item_4405.html
 

Windows 7 taskbar и Delphi

Опубликовано 14.03.2010 г. 19:26

Для управления состоянием и значением прогресса текущего действия, отображаемого на значке панели задачи приложения в СО windows 7 используются COM интерфейс ITaskBarList3 описанный в ShlObj.pas (Delphi2010). Для использования данного функционала создадим новое приложение с одной формой MainForm, расположим на нем stateSelect (TRadioGroup) и progressBar (TTrackBar). Для удобства опишем тип-запись TTaskState с полями имя-значение:

type TTaskState = record
        name : string;
        value : byte;
     end;

и объявим массив констант для описания возможных значений состояний, отображаемых на панели задач.

const
    taskStates : array [0..4] of TTaskState = (
            (name : 'TBPF_NOPROGRESS';    value : TBPF_NOPROGRESS),
            (name : 'TBPF_INDETERMINATE'; value : TBPF_INDETERMINATE),
            (name : 'TBPF_NORMAL';        value : TBPF_NORMAL ),
            (name : 'TBPF_ERROR';         value : TBPF_ERROR),
            (name : 'TBPF_PAUSED';        value : TBPF_PAUSED)
        );

В раздел private описания класса TMainForm добавим описание нужного интерфейса, переменные для хранения значений состояния и прогресса, а так же методы для изменения данных значений.

  private
    taskBarList : ITaskBarList3;

    fState : integer;
    fProgress : integer;

    procedure setTaskState(newState:integer);
    procedure setTaskProgress(newValue : integer);

в разделе public объявим соответствующие свойства для управления состоянием и прогрессом.

    property state : integer read fState write setTaskState;
    property progress : integer read fProgress write setTaskProgress;

в событии создания формы FormCreate создадим COM объект для работы с с панелью задач Windows (ITaskBarList), проверим поддерживает ли ОС требуемый нам интерфейс ITaskBarList3 и заполним stateSelect значениями из массива taskStates.

procedure TMainForm.FormCreate(Sender: TObject);
var tbList : ITaskBarList;
    hr : HRESULT;
    state : TTaskState;
begin
    tbList := CreateComObject(CLSID_TaskBarList) as ITaskBarList;
    hr := tbList.QueryInterface(IID_ITaskBarList3,taskBarList);
    if hr <> S_OK then begin
        taskBarList := nil;
           tbList._Release;
    end;

    for state in TaskStates do
        stateSelect.Items.AddObject(state.name,TObject(state.value));
end;

В обработчике события OnChange stateSelect будем устанавливать состояние значка панели задач, в зависимости от выбранного пункта. Для этого определим обработчик события и метод записи свойства state следующим образом

procedure TMainForm.StateSelectClick(Sender: TObject);
begin
    self.state :=  stateSelect.ItemIndex;
end;

procedure TMainForm.setTaskState(newState: Integer);
begin
    if assigned(taskBarList) then
        taskBarList.SetProgressState(handle,taskStates[newState].value);
end;

Установим значения min/max progressBar'a в 0/100 и опишем обработчик события изменения его значения, а также метод изменения значения свойства progress

procedure TMainForm.progressBarChange(Sender: TObject);
begin
    self.progress := progressBar.Position;
end;

procedure TMainForm.setTaskProgress(newValue: Integer);
begin
    if assigned(taskBarList) then
        taskBarList.SetProgressValue(handle,newValue,100);
end;

Результаты работы данного кода представлены на рисунке.

апдейт от 14.06.2011г.: тестовый проект с установкой состояния и прогресса
зы: приведенному коду в статье не соответствует. реализация более корректная.

Метки:  taskbar  |  windows 7 

Комментарии

Ale-nov11
20.07.2010 в 17:02
либо я что-то не так сделал, но это не работает
ter
05.08.2010 в 20:46
вобще должно работать (:
по крайней мере у меня все работало (:
хотя конечно мб я где то с копирование исходного кода ошибся.
могу выложить проект если надо.
Константин
03.10.2011 в 15:27
Очень интересная тема!
Спасибо за пример.

Просмотрев код... написал пару маленьких классов для синхронизации отображения TProgressBar с прогрессом на кнопке в панели задач.

Сделал демку (выложил у себя на сайте): http://optitrex.ru/downloader?file=taskbar_list_progress_demo.exe

Если кому интересно? Пишите. Поделюсь исходниками.
ter
03.10.2011 в 17:23
имхо лучше наследника сделать от TProgressBar с возможностью управления и таскбаром. только тут будет небольшая загвоздка, с тем, что если на форме два прогресс бара, то какой из них будет управлять таскбаром. решать наверное как то проще через class property в которых будет ссылка на интерфейс таскбара.
Константин
04.10.2011 в 09:14
Если делать наследника, то это уже компонент... Его устанавливать надо.
В общем вот, что у меня получилось:
  {$IFDEF DELPHI_2009_UP}{$REGION 'Documentation'}{$ENDIF}
  ///	Класс доступа к интерфейсам панели задач Windows
  {$IFDEF DELPHI_2009_UP}{$ENDREGION}{$ENDIF}
  TUcTaskbarList = class
  private
    fTaskbarList:  ITaskbarList;
    fTaskbarList2: ITaskbarList2;
    fTaskbarList3: ITaskbarList3;
    fTaskbarList4: ITaskbarList4;
  protected
    procedure ClearTaskbarLists;
  public
    constructor Create;
    destructor Destroy; override;

    property TaskbarList:  ITaskbarList  read fTaskbarList;
    property TaskbarList2: ITaskbarList2 read fTaskbarList2;
    property TaskbarList3: ITaskbarList3 read fTaskbarList3;
    property TaskbarList4: ITaskbarList4 read fTaskbarList4;
  end;

  {$IFDEF DELPHI_2009_UP}{$REGION 'Documentation'}{$ENDIF}
  ///	Класс-контроллер. Синхронизирует отображение некоторого
  ///	прогресса на ProgressBar и на кнопке панели задач.
  {$IFDEF DELPHI_2009_UP}{$ENDREGION}{$ENDIF}
  TUcTaskbarListProgress = class
  private
    fTBL: TUcTaskbarList;
    fWinHandle: HWND;
    fPrBar: TProgressBar;
    FMax: Integer;
    FPosition: Integer;
    FMin: Integer;
    FState: TProgressBarState;
    FStyle: TProgressBarStyle;
    FProgressState: Integer;
    FShowProgressOnTaskbar: Boolean;
    procedure SetMax(const Value: Integer);
    procedure SetPosition(const Value: Integer);
    procedure SetMin(const Value: Integer);
    procedure UpdateTaskbarListProgress;
    procedure UpdateTaskbarListProgressState;
    procedure SetState(const Value: TProgressBarState);
    procedure SetStyle(const Value: TProgressBarStyle);
    procedure SetProgressState(const Value: Integer);
    procedure SetShowProgressOnTaskbar(const Value: Boolean);
  protected
    property ProgressState: Integer read FProgressState write SetProgressState;
  public
    constructor Create;
    destructor Destroy; override;
    {$IFDEF DELPHI_2009_UP}{$REGION 'Documentation'}{$ENDIF}
    ///	Инициализация контроллера
    ///	Хендл окна имеющего кнопку на панели задач.
    ///	На Этой кнопке будет отображаться прогресс.
    ///	Компонент для отображения прогресса.
    {$IFDEF DELPHI_2009_UP}{$ENDREGION}{$ENDIF}
    procedure Init(WindowHandle: HWND; ProgressBar: TProgressBar);
    property Max: Integer read FMax write SetMax;
    property Min: Integer read FMin write SetMin;
    property Position: Integer read FPosition write SetPosition;
    property Style: TProgressBarStyle read FStyle write SetStyle;
    property State: TProgressBarState read FState write SetState;
    property ShowProgressOnTaskbar: Boolean read FShowProgressOnTaskbar
                                            write SetShowProgressOnTaskbar;
  end;
ter
04.10.2011 в 11:16
ну если наследника сделать, то можно его и динамически использовать, не обязательно компилить в пакет и устанавливать.
Ghost
22.04.2014 в 10:50
Ребят, а кто знает, почему когда подключаешь проект с рабочим таскбаром к другому проекту, с 4 формами то он просто не отображается? Прогресс бар работает, а на панели задач чисто
Chaser
16.02.2017 в 13:16
Привет! Так есть готовый рабочий вариант с иходниками? Тк текущий архив недоступен, а код нерабочий.
- Имя
- e-mail*
- Сайт
вы можете использовать теги [i],[b],[code],[quote]
Дополнительно