【问题标题】:Delphi 10.2 how to use the ZipProgressDelphi 10.2如何使用ZipProgress
【发布时间】:2018-08-18 23:09:27
【问题描述】:

较早的 StackOverflow 主题提供了一些示例代码,用于在使用 TZipFile 时使用进度事件:

Using Delphi Toyko creating a Zip file onprocess example

如果我将它用作 MainForm,我可以使示例工作。但是我在尝试将代码转换为在单独的单元中工作时完全受阻。

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

E2009 不兼容的类型:“方法指针和常规过程”

错误触发就行了:

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 提供有用的示例代码,那就太好了!

【问题讨论】:

  • 那么我之前的评论给了你答案。 OnZipProgressEvent 需要是一个对象方法,不是一个独立的过程。不要试图对事件做出自己的声明。将适当的单位添加到 uses 子句,它将为您声明它,然后使事件处理程序成为类方法,而不是独立的过程。它被声明为procedure of object,这意味着它需要是一个对象方法。
  • 感谢您的快速回答。不幸的是,我在研究过程中看到了这个建议的变化,我不知道如何实现这一点。这就是为什么我正在寻找一个例子。

标签: delphi delphi-10.2-tokyo


【解决方案1】:

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

这应该可以帮助您入门。将您自己的代码添加到jrCreateZipFromFolderTMyZipProgress.ShowZipProgress 的实现中,正如我在下面的代码cmets 中所说的那样。我将它设为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.

【讨论】:

  • 非常感谢。这很好地完成了工作。
猜你喜欢
  • 2018-09-21
  • 2020-01-30
  • 1970-01-01
  • 1970-01-01
  • 2018-12-25
  • 2020-03-08
  • 2020-09-05
  • 1970-01-01
  • 2018-08-14
相关资源
最近更新 更多