An earlier StackOverflow topic provides some sample code for using the progress event while using TZipFile
:
Using Delphi Toyko creating a Zip file onprocess example
I am able to make the example work if I use it as a MainForm. But I am completely stymied in trying to convert the code to work in a separate unit.
Every time I try to compile the code as a unit, I get an error message:
E2009 Incompatible types: 'method pointer and regular procedure'
The error is triggered on the line:
TZipFile.ZipDirectoryContents('C:\temp\Test.zip','c:\temp\zipTest',zcDeflate,OnZipProgressEvent);
I've researched in every way I could think of, and tried all manner of alternatives, but no luck.
Can anyone explain how to make the OnZipProgressEvent
code work in a separate unit?
This is the unit code that I have so far:
unit ZipDelphiNative;
interface
uses
Windows,SysUtils, StrUtils, Variants, MaskUtils, Dialogs,StdCtrls,
Graphics, Menus,Classes, ClipBrd, System.Zip, Winapi.Messages,
System.Generics.Collections, system.ioutils, system.types,
Forms,ComCtrls, DateUtils;
Type
TZipProgressEvent = procedure(Sender: TObject; FileName: string; Header: TZipHeader; Position: Int64) of object;
// TZipProgressEvent = procedure(Sender: TObject; FileName: string; Header: TZipHeader; Position: Int64);
function jrCreateZipFromFolder(inZipName : string; inSourcePath : string; inTargetPath : string) : boolean;
procedure OnZipProgressEvent (Sender: TObject; FileName: string; Header: TZipHeader; Position: Int64);
var
PreviousFilename : string;
implementation
uses
Unit1;
function jrCreateZipFromFolder(inZipName : string; inSourcePath : string; inTargetPath : string) : boolean;
//inTargetPath is already confirmed to be valid
//Zips all files in inSourcePath & subfolders
var
Zip : TZipFile;
// ZipCallBack: TZipProgressEvent;
sZipName, sSourceName : string;
begin
result := true;
// ZipCallBack := OnZipProgressEvent;
sZipName := IncludeTrailingBackslash(inTargetPath) + inZipName;
sSourceName := IncludeTrailingBackslash(inSourcePath) ;
Zip := TZipFile.Create;
try
if FileExists(sZipName) then
DeleteFile(sZipName);
// zip.ZipDirectoryContents(sZipName, sSourceName, zcDeflate, ZipCallBack); //do not store folder too
zip.ZipDirectoryContents(sZipName, sSourceName, zcDeflate, OnZipProgressEvent); //do not store folder too
zip.Close;
except
result := false;
end;
FreeAndNil(Zip);
end;
procedure OnZipProgressEvent(Sender: TObject; FileName: string;
Header: TZipHeader; Position: Int64);
begin
if PreviousFilename <> FileName then
begin
PreviousFilename := FileName;
unit1.Form1.ProgressBar1.Max := Header.UncompressedSize;
unit1.Form1.ProgressBar1.Position := Position;
end
else
// Unit1.Form1.ProgressBar1.Position := (Position * 100) div Header.UncompressedSize ;
Unit1.Form1.ProgressBar1.Position := Position;
Application.ProcessMessages;
end;
end.
I have tried defining TZipProgressEvent
with and without of object
. I have two options in this code for using the TZipProgressEvent
, either like the original example, or the commented out version of defining ZipCallBack
. Both work under different circumstances when used in a Form. Neither work when used in this unit.
So, I am baffled as to how to make this work. It would sure be nice if Embarcadero offered useful sample code!
TZipProgressEvent
is declared as being of object
, which means it must be a method of an object (class). So in order to implement it, you need to declare a class that implements that method with that signature (the signature in the TZip
class, not the one you made up).
This should get you started. Add your own code to the implementation of jrCreateZipFromFolder
and TMyZipProgress.ShowZipProgress
, as I've said in the code comments below. I've made it a class procedure
so that you don't have to create an instance of TMyZipProgress
to use it.
unit ZipDelphiNative;
interface
function jrCreateZipFromFolder(inZipName, inSourcePath, inTargetPath: string): Boolean;
implementation
{ TMyZip }
uses
System.Zip;
type
TMyZipProgress = class(TObject)
private
class procedure ShowZipProgress(Sender: TObject; FileName: string;
Header: TZipHeader; Position: Int64);
end;
function jrCreateZipFromFolder(inZipName, inSourcePath,
inTargetPath: string): boolean;
var
FZip: TZipFile;
begin
Result := False;
FZip := TZipFile.Create;
try
// Rest of your zip file code here, then call
FZip.ZipDirectoryContents(sZipName, sSourceName, zcDeflate, TMyZipProgress.ShowZipProgess);
Result := True;
finally
FZip.Free;
end;
end;
class procedure TMyZipProgress.ShowZipProgress(Sender: TObject; FileName: string;
Header: TZipHeader; Position: Int64);
begin
// Show your progress here, whatever it needs to do
end;
end.