1

While performing long operations, some applications shows a progressbar behind the application icon, in the taskbar.

Screenshot of a taskbar with a progress bar in one of the buttons.

...

Screenshot of a taskbar with a progress bar in one of the buttons.

How can this progress indicator be set from a Delphi application?

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
Fabrizio
  • 7,603
  • 6
  • 44
  • 104
  • 1
    When you add an image to your Q, please replace the "enter image description here" placeholder with an informative description of the image (like "Screenshot of a taskbar with a progress bar in one of the buttons"). A visually impaired user, who uses a screen reader, will find that text much more helpful. Also, search engines like Google will do a much better job understanding the image. – Andreas Rejbrand Nov 21 '19 at 13:24
  • That's the task *button*, not bar. The bar holds all buttons. – AmigoJack Nov 21 '19 at 14:27
  • https://stackoverflow.com/a/5816222/4299358 also applies - didn't that turn up in your search results? – AmigoJack Nov 21 '19 at 14:30
  • Also: https://stackoverflow.com/questions/8633389/how-to-get-applications-windows-taskbar-button-to-show-progress-of-progress-bar?rq=1 (in the "Related" panel to the right). – Andreas Rejbrand Nov 21 '19 at 14:33
  • @AndreasRejbrand: thanks for suggestion, I will set an image description next time – Fabrizio Nov 21 '19 at 14:39
  • 1
    Very strange, both questions wasn't in the "Similar questions" box – Fabrizio Nov 21 '19 at 14:40
  • Not so strange, SO's internal search tends to be pretty weak at finding similar questions. It's important that you do thorough research before you post here. – David Heffernan Nov 25 '19 at 15:23

2 Answers2

8

In modern Delphi versions, you have the TTaskbar component in the Win32 part of the component palette.

Drop that one on your form, set ProgressState (to Normal, say), ProgressMaxValue (to 100, say), and ProgressValue (to 50, say).

In my experience, this component is buggy -- or at least it has been in earlier versions. So be careful.

A safer alternative, of course, is to use the Win32 API directly. See the official documentation for ITaskbarList3.

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
1

Here you have an example (link):

unit uMainTest;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ObjectArray, ShlObj, ExtCtrls, ComCtrls, ActiveX, ComObj,
  ImgList, CommCtrl, PropSys;

type
  TfrmMain = class(TForm)
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    Button2: TButton;
    trackBar: TTrackBar;
    GroupBox5: TGroupBox;
    chkState1: TCheckBox;
    chkState2: TCheckBox;
    chkState3: TCheckBox;
    chkState4: TCheckBox;
    Button3: TButton;
    procedure FormCreate(Sender: TObject);
    procedure btProgressBarDemoClick(Sender: TObject);
    procedure btProgressStateClick(Sender: TObject);
    procedure trackBarChange(Sender: TObject);
    procedure btConfigureTasksClick(Sender: TObject);
  private
    TaskBar: ITaskBarList3;
    msgTaskbarButtonCreated: cardinal;

  protected
    procedure WndProc(var Message: TMessage); override;
  public

  end;

var
  frmMain: TfrmMain;

implementation

uses Registry, ShellApi, uFileRegistration ;

{$R *.dfm}

procedure TfrmMain.btProgressBarDemoClick(Sender: TObject);
begin
  TaskBar.SetProgressValue(Handle, trackBar.Position, trackBar.Max);
end;

procedure TfrmMain.btProgressStateClick(Sender: TObject);
var
  Flags: integer;
begin
  Flags := TBPF_NOPROGRESS;
  if chkState1.Checked then
    Flags := Flags or chkState1.Tag;
  if chkState2.Checked then
    Flags := Flags or chkState2.Tag;
  if chkState3.Checked then
    Flags := Flags or chkState3.Tag;
  if chkState4.Checked then
    Flags := Flags or chkState4.Tag;
  TaskBar.SetProgressState(Handle, Flags);
end;

procedure TfrmMain.btConfigureTasksClick(Sender: TObject);
var
  JumpList: ICustomDestinationList;
  RemovedDestination: IObjectArray;
  TaskList: IObjectCollection;
  pcMaxSlots: cardinal;
  Link1: IShellLink;
begin
  JumpList := CreateComObject(CLSID_DestinationList) as ICustomDestinationList;
  OleCheck(JumpList.BeginList(pcMaxSlots, IID_IObjectArray,
    RemovedDestination));
  try

    // A présent, on prépare une nouvelle liste de tâches à ajouter dans la
    // JumpList.
    TaskList := CreateComObject(CLSID_EnumerableObjectCollection)
      as IObjectCollection;

    // Enfin, on définit la liste des tâches en appelant AddUserTasks.
    OleCheck(JumpList.AddUserTasks(TaskList));
  except
    // En cas d'erreur, il faut annuler la liste en cours de définition
    JumpList.AbortList;
    raise; // Puis on redéclenche l'exception.
  end;
  OleCheck(JumpList.CommitList);
end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  msgTaskbarButtonCreated := RegisterWindowMessage('TaskbarButtonCreated');

  OleCheck(SetCurrentProcessExplicitAppUserModelID('Dvp.Delphi.DemoTaskbar.1'));
end;

procedure TfrmMain.trackBarChange(Sender: TObject);
begin
  TaskBar.SetProgressValue(Handle, trackBar.Position, trackBar.Max);
end;

procedure TfrmMain.WndProc(var Message: TMessage);
begin
  if Message.Msg = msgTaskbarButtonCreated then
    TaskBar := CreateComObject(CLSID_TaskbarList) as ITaskBarList3
  else
    inherited WndProc(Message);
end;

end.
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770