Delphi10.2如何使用ZipProgress

Delphi 10.2 how to use the ZipProgress

一个较早的 Whosebug 主题提供了一些示例代码,用于在使用 TZipFile:

时使用进度事件

Using Delphi Toyko creating a Zip file onprocess example

如果我将它用作 MainForm,我能够使示例工作。但是我完全无法尝试将代码转换为在单独的单元中工作。

每次尝试将代码编译为一个单元时,都会收到错误消息:

E2009 Incompatible types: 'method pointer and regular procedure'

线路触发错误:

TZipFile.ZipDirectoryContents('C:\temp\Test.zip','c:\temp\zipTest',zcDeflate,OnZipProgressEvent);

我研究了所有我能想到的方法,并尝试了所有的替代方法,但没有成功。

谁能解释一下如何使 OnZipProgressEvent 代码在单独的单元中工作?

这是我目前拥有的单位代码:

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. 

我试过定义 TZipProgressEvent 有无 of object。在这段代码中,我有两个使用 TZipProgressEvent 的选项,或者像原始示例一样,或者定义 ZipCallBack 的注释掉的版本。当在表单中使用时,两者在不同的情况下工作。在本机中使用时均无效。

所以,我对如何进行这项工作感到困惑。如果Embarcadero能提供有用的示例代码就更好了!

TZipProgressEvent 被声明为 of object,这意味着它必须是一个对象的方法 (class)。因此,为了实现它,您需要声明一个 class 来实现具有该签名的方法(TZip class 中的签名,而不是您编写的签名)。

这应该可以帮助您入门。将您自己的代码添加到 jrCreateZipFromFolderTMyZipProgress.ShowZipProgress 的实现中,正如我在下面的代码注释中所说的那样。我已将其设为 class procedure,因此您无需创建 TMyZipProgress 的实例即可使用它。

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.