5

I am using the Open Source Abbrevia Components to Archive some Files into a single Zip, whilst this is happening I am using the TAbMeter Gauge to display the progress.

I would prefer to use the TProgressBar for this purpose instead though (maintaining a standard interface with Windows).

How may I use a TProgressBar instead of the TAbMeter? I know I could code the progress myself, but seeing as the Abbrevia Components already have this done in the TAbMeter, I see no sense in rewriting it.

If I could even access the Position property of the TAbMeter I could simulate the TProgressBar's progress by synchronizing with the TAbMeter.

Here is a snippet, FileNames is a TStringList containing the Filenames to archive..

procedure ArchiveFiles(SaveAs: string; ProgressBar: TAbMeter);
var
  AZipper: TAbZipper;
  i: Integer;
begin
  AZipper := TAbZipper.Create(nil);
  try
    AZipper.AutoSave := False;
    AZipper.BaseDirectory := ExtractFilePath(SaveAs);
    AZipper.ArchiveSaveProgressMeter := ProgressBar;
    AZipper.FileName := SaveAs;
    AZipper.StoreOptions := AZipper.StoreOptions + [soStripDrive, soRemoveDots]
                                                 - [soStripPath];
    AZipper.TempDirectory := GetTempDirectory;

    try
      Screen.Cursor := crHourGlass;
      ProgressBar.Visible := True;

      for i := 0 to FileList.Count - 1 do
      begin
        AZipper.AddFiles(FileList.Strings[i], 0);
      end;

    finally
      AZipper.Save;
      AZipper.CloseArchive;

      ProgressBar.Visible := False;
      Screen.Cursor := crDefault;
    end;

  finally
    AZipper.Free;
  end;
end;
Robert Harvey
  • 178,213
  • 47
  • 333
  • 501

2 Answers2

5

You are presumably setting the ArchiveSaveProgressMeter somewhere in your code. You can simply stop doing this and instead set the OnArchiveSaveProgress event. Then you need to supply an event with this signature:

procedure(Sender: TObject; Progress: Byte; var Abort: Boolean) of object;

You would respond to receipt of such an event by updating the Position value of the progress bar in your UI.

The method that surfaces this progress event also handles the progress meter version:

procedure TAbCustomZipper.DoArchiveSaveProgress(
  Sender: TObject; Progress: Byte; var Abort : Boolean);
begin
  Abort := False;
  if Assigned(FArchiveSaveProgressMeter) then
    FArchiveSaveProgressMeter.DoProgress(Progress);
  if Assigned(FOnArchiveSaveProgress) then
    FOnArchiveSaveProgress(Self, Progress, Abort);
end;

So the designers of the component have simply provided two alternative routes to receiving progress: the meter or a callback.


In order to handle progress from a callback you need to write a method like this:

procedure TMyMainForm.OnArchiveSaveProgress(
  Sender: TObject; Progress: Byte; var Abort: Boolean);
begin
  FProgressBar.Position := Progress;
end;

You then assign this event handler to OnArchiveSaveProgress, most likely in the IDE. It's an identical procedure to assigning an OnClick event to a button.


Note: I've never used Abbrevia so I may have picked out a different component from the one you are using. However, all the components that interact with meters, also offer progress via a callback so this basic approach will work no matter which component you use.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Thanks for the information, I am not sure how to use or manage callbacks though, so I am not sure how I could even implement a TProgressBar here based on the information you provided. –  Dec 01 '11 at 15:50
  • OK, I've updated to try to help you. Think of the progress callback in the same way that you think of a button `OnClick` event handler. – David Heffernan Dec 01 '11 at 16:10
  • Thats great, works perfect thanks David, I learned something new :) –  Dec 01 '11 at 16:40
  • +1. Small terminology nitpick, though. The `OnArchiveSaveProgress` method is not a callback - this is Delphi, and they're called `event handlers` :). It's an event handler, triggered when it's assigned and then called by `DoArchiveSaveProgress` (just like a button `OnClick` event, as you mention in your last comment). A `callback` is generally a stand-alone procedure passed as a function pointer to an API (for instance, `CopyFileEx` and its' `LPPROGRESS_ROUTINE lpProgressRoutine` parameter). :) – Ken White Dec 01 '11 at 17:58
  • @ken well, you could view an event handler as a form of callback but I take your point. – David Heffernan Dec 01 '11 at 18:08
  • 1
    :) As I said, it's a terminology thing. That's why I posted the :) - not a big deal, just might be confusing to people who only write code in Delphi. It's clearer to call it an event handler if you can create it through the Object Inspector Events tab. – Ken White Dec 01 '11 at 18:11
2

In case it helps anyone else, I've created a new TAbProgressBar component that can be used instead of TAbMeter. They both implement the same interface, so it works with the same Archive*ProgressMeter properties. Just update Abbrevia from Subversion and recompile the AbbreviaVCL and AbbreviaVCLDesign packages.

Zoë Peterson
  • 13,094
  • 2
  • 44
  • 64