You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++ Builder中基于ZipDirectoryContents回调实现压缩进度条的问题

借助ZipDirectoryContents回调实现压缩进度条的代码修正

原代码存在的问题:

  • 回调传递错误:调用ZipDirectoryContents时错误执行了OnZipProgressEvent(),应该传递回调函数指针,而非直接调用函数。
  • 未定义变量:函数内使用的sZipName、sSourceName未声明,属于无效变量。
  • catch块语法错误:catch(...)后的代码未用大括号包裹,导致编译失败。
  • 重复定义回调类型:TZipProgressEvent已经在System.Zip.hpp中定义,自行typedef会引发类型冲突。
  • 逻辑错误:仅当目标Zip文件存在时才执行压缩,不符合创建新压缩包的需求。
  • 全局变量风险:PreviousFilename作为全局变量,易引发意外问题,建议改为类成员。
  • TZipFile使用不当:手动实例化TZipFile后未正确处理打开逻辑,代码冗余。

修正后的完整代码

头文件(Unit1.h)

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <System.Zip.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE-managed Components
    TProgressBar *ProgressBar1;
private:    // User declarations
    String FPreviousFilename; // 替换全局变量为类成员
public:     // User declarations
    __fastcall TForm1(TComponent* Owner);
    bool __fastcall CreateZipFromFolder(const String& InZipName, const String& InSourcePath);
    void __fastcall OnZipProgressEvent(TObject* Sender, String FileName, TZipHeader Header, __int64 Position);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

实现文件(Unit1.cpp)

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner), FPreviousFilename(_D(""))
{
}
//---------------------------------------------------------------------------
bool __fastcall TForm1::CreateZipFromFolder(const String& InZipName, const String& InSourcePath)
{
    try
    {
        // 使用TZipFile静态方法简化压缩逻辑,自动处理文件创建/覆盖
        TZipFile::ZipDirectoryContents(
            InZipName,
            InSourcePath,
            zcDeflate,
            &OnZipProgressEvent // 正确传递回调函数指针
        );
        return true;
    }
    catch(const Exception& E)
    {
        ShowMessage(_D("压缩错误: ") + E.Message);
        return false;
    }
    catch(...)
    {
        ShowMessage(_D("未知压缩错误"));
        return false;
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OnZipProgressEvent(TObject* Sender, String FileName, TZipHeader Header, __int64 Position)
{
    if (FPreviousFilename != FileName)
    {
        FPreviousFilename = FileName;
        ProgressBar1->Max = Header.UncompressedSize;
        ProgressBar1->Position = Position;
    }
    else
    {
        ProgressBar1->Position = Position;
    }
    // 确保界面响应,避免卡顿
    Application->ProcessMessages();
}
//---------------------------------------------------------------------------

关键修正说明

  • 回调传递:用&OnZipProgressEvent传递类成员函数的__closure指针,符合C++Builder回调类型要求。
  • 变量处理:将全局变量改为类成员FPreviousFilename,避免全局作用域污染;使用函数参数接收输入路径,保证代码通用性。
  • 语法修复:给catch块添加大括号,同时捕获Exception类型以输出具体错误信息,便于调试。
  • 简化逻辑:使用TZipFile的静态ZipDirectoryContents方法,无需手动管理TZipFile实例的创建和关闭,代码更简洁可靠。
  • 界面优化:将Application->ProcessMessages()移到分支外,确保每次进度更新都处理消息,避免界面假死。

内容的提问来源于stack exchange,提问作者hexadecimal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 01:55:18