Search code examples
callbackc++builder

c++ builder ZipProgress callback for the progress bar


I have a simple form, and I'm trying to work with the ProgressBar when a .zip file is being created, based on the ZipDirectoryContents callback. I have seen some Delphi example in the forum, but I don't know it well, and I get several errors. Here an example:

.cpp

#include <system.zip.hpp>

String PreviousFilename;
bool __fastcall createZipFromFolder( String inZipName,
                                     String inSourcePath,
                                     String inTargetPath )
{
      bool result = true;
      sZipName = "C:\\test\\testBar.zip";
      sSourceName = "C:\\test2";
      TZipFile* Zip = new TZipFile();
      try{
        if ( FileExists( sZipName ) ){
            Zip->ZipDirectoryContents( sZipName,                // destiny
                                       sSourceName,             // to include
                                       zcDeflate,               // compression mode
                                       OnZipProgressEvent() );  // <--- p callback
            Zip->Close();
        }
      }
      catch(...){
        result = false;
        ShowMessage("Error");
      }
      delete Zip;
      Zip = NULL;
      return result;
}

void __fastcall OnZipProgressEvent( TObject* Sender, String FileName, TZipHeader Header, __int64 Position )
{
  if ( PreviousFilename != FileName ){
    PreviousFilename = FileName;
    Form1->ProgressBar1->Max = Header.UncompressedSize;
    Form1->ProgressBar1->Position = Position;
  }
  else{
    Form1->ProgressBar1->Position = Position;
    Application->ProcessMessages();
  }
}

.h

#include <System.Zip.hpp>

public:     // User declarations
    __fastcall TForm1(TComponent* Owner);

    typedef void __fastcall ( __closure * TZipProgressEvent )( TObject*,
                                                               String,
                                                               TZipHeader,
                                                               __int64 );
    bool __fastcall createZipFromFolder( String inZipName,
                                         String inSourcePath,
                                         String inTargetPath );
    void __fastcall OnZipProgressEvent( TObject* Sender,
                                        String FileName,
                                        TZipHeader Header,
                                        __int64 Position );
};
extern PACKAGE TForm1 *Form1;
extern String PreviousFilename;

#endif

Solution

  • When calling Zip->ZipDirectoryContents(), you need to change OnZipProgressEvent() to &OnZipProgressEvent instead. You are trying to call the callback (with missing parameters) when you should be passing its address.

    Also, in your .cpp file, both createZipFromFolder() and OnZipProgressEvent() need to be defined as being members of your Form class.

    Also, in OnZipProgressEvent(), the TZipHeader parameter needs to be passed by const reference rather than by value, per the documentation.

    Try this:

    Unit1.h

    ...
    
    class TForm1 : public TForm
    {
        ...
    private:        // User declarations
        String PreviousFilename;
        void __fastcall OnZipProgressEvent( TObject* Sender,
                                            String FileName,
                                            const TZipHeader &Header,
                                            __int64 Position );
    
    public:     // User declarations
        __fastcall TForm1(TComponent* Owner);
        
        bool __fastcall createZipFromFolder( String inZipName,
                                             String inSourcePath,
                                             String inTargetPath );
    };
    
    extern PACKAGE TForm1 *Form1;
        
    #endif
    

    Unit1.cpp

    ...
    #include "Unit1.h"
    #include <System.Zip.hpp>
    
    bool __fastcall TForm1::createZipFromFolder( String inZipName,
                                                 String inSourcePath,
                                                 String inTargetPath )
    {
        bool result = true;
        sZipName = _D("C:\\test\\testBar.zip");
        sSourceName = _D("C:\\test2");
        PreviousFilename = _D("");
        TZipFile* Zip = new TZipFile();
        try{
            if ( FileExists( sZipName ) ){
                Zip->ZipDirectoryContents( sZipName,                // destiny
                                            sSourceName,             // to include
                                            zcDeflate,              // compression mode
                                            &OnZipProgressEvent );  // <--- p callback
                Zip->Close();
            }
        }
        catch(...){
            result = false;
            ShowMessage(_D("Error"));
        }
        delete Zip;
        Zip = NULL;
        return result;
    }
    
    void __fastcall TForm1::OnZipProgressEvent( TObject* Sender,
                                                String FileName,
                                                const TZipHeader &Header,
                                                __int64 Position )
    {
        if ( PreviousFilename != FileName ){
            PreviousFilename = FileName;
            ProgressBar1->Max = Header.UncompressedSize;
            ProgressBar1->Position = Position;
        }
        else{
            ProgressBar1->Position = Position;
            Application->ProcessMessages();
        }
    }