Progress Notifications: Using Callback Objects
Applies To: All

Introduction

The ZipArchive Library uses callback objects to notify about the progress of an archive processing.

Creating Callback Objects

To be notified about the progress of various actions (see CZipActionCallback::CallbackType for possibilities), you need to:

Order of Methods Calls

You can also override other methods of the CZipActionCallback class to be notified about starting and ending stages of the process. The methods are called in the following order:

Controlling the Frequency of Calling Callbacks

To control how often the CZipCallback::Callback() method is called, override the CZipActionCallback::GetStepSize() method and return the step size value for a given callback type. If you use one CZipActionCallback object for multiple callback types, you may find out for which callback type the step size is requested by examining the CZipActionCallback::m_iType value from within the CZipActionCallback::GetStepSize() method.
Sample Code
class CProgressCallback : public CZipActionCallback
{    
    void Init(LPCTSTR lpszFileInZip, LPCTSTR lpszExternalFile) 
    {
        CZipActionCallback::Init(lpszFileInZip, lpszExternalFile);
        // we can display initial information here
        LPCTSTR lpszAction;
        switch (m_iType)
        {
            case CZipActionCallback::cbAdd:
                lpszAction = _T("Adding");
                break;
            case CZipActionCallback::cbExtract:
                lpszAction = _T("Extracting");
                break;
            case CZipActionCallback::cbSave:
                lpszAction = _T("Saving");
                break;
            default:
                lpszAction = _T("???");
        }
        _tprintf(_T("\r\n%s...\r\n"), lpszAction);
    }

    bool Callback(ZIP_SIZE_TYPE uProgress)
    {
#ifdef _ZIP_ZIP64
        _tprintf(_T("Processed %I64u of %I64u (%I64u left)            \r"), 
            m_uProcessed, m_uTotalToProcess, LeftToProcess());
#else
        _tprintf(_T("Processed %u of %u (%u left)            \r"), 
            m_uProcessed, m_uTotalToProcess, LeftToProcess());
#endif
        // return false here to abort processing
        return true;
    }

    // override the method to adjust the frequency of calling the callback
    int GetStepSize()
    {        
        return m_iType == cbSave ? 1024 : 64;
    }
};

void Progress()
{
    LPCTSTR zipFileName = _T("C:\\Temp\\test.zip");
    CZipArchive zip;    
    CProgressCallback callback;
    // set one callback for all notifications
    zip.SetCallback(&callback);
    zip.Open(zipFileName, CZipArchive::zipCreate);    
    zip.AddNewFile(_T("C:\\Temp\\file.dat"));
    zip.Close();
    zip.Open(zipFileName);
    zip.ExtractFile(0, _T("C:\\Temp"), false, _T("file.ext"));
    zip.Close();
}

Multiple Actions Callbacks

When processing multiple files in one step, there is additional information available about the global progress. It is available for CZipActionCallback::cbMultiActions callback types. It can be requested with the CZipActionCallback::GetMultiActionsInfo() method call.

Order of Methods Calls

There are additional methods called when processing multiple files. They are called in the following order:
Sample Code
class CMultiProgressCallback : public CZipActionCallback
{    
    bool Callback(ZIP_SIZE_TYPE uProgress)
    {
        if (m_iType == cbCalculateForMulti)
        {
            LPCTSTR FormatSymbol = _T("%I64u");
#ifdef _ZIP_ZIP64
            _tprintf(_T("Found %I64u files so far          \r\n"), m_uProcessed);
#else
            _tprintf(_T("Found %u files so far          \r\n"), m_uProcessed);
#endif
            return true;
        }

        CMultiActionsInfo* pMulti = GetMultiActionsInfo();
        ASSERT(pMulti);

#ifdef _ZIP_ZIP64
        _tprintf(_T("Current File: %I64u of %I64u, Total Bytes: %I64u of %I64u        \r"), 
#else
        _tprintf(_T("Current File: %u of %u, Total Bytes: %u of %u        \r"), 
#endif
        m_uProcessed, m_uTotalToProcess,
        pMulti->m_uBytesProcessed, pMulti->m_uTotalBytesToProcess);

        return true;
    }

    int GetStepSize()
    {        
        // Let's the call the Callback method very often to better illustrate
        // the functionality.
        // Normally this would degrade performance with some callback types.
        return 1;
    }

    // override to be notified about every file processed
    bool MultiActionsNext()
    {    
        // call the base class' method
        if (CZipActionCallback::MultiActionsNext())
        {
            CMultiActionsInfo* pMulti = GetMultiActionsInfo();
#ifdef _ZIP_ZIP64
            _tprintf(_T("\n\rFiles Processed: %I64u of %I64u     \n\r"), 
#else
            _tprintf(_T("\n\rFiles Processed: %u of %u     \n\r"), 
#endif
            pMulti->m_uFilesProcessed, pMulti->m_uTotalFilesToProcess);
            return true;
        }
        else
            // Processing was requested to be stopped.
            // It won't happen in this sample code, because
            // the Callback method always returns true.
            return false;
    }
};

void ProgressMulti()
{
    CZipArchive zip;    
    CMultiProgressCallback callback;
    // register for 
    zip.SetCallback(&callback, 
        CZipActionCallback::cbMultiAdd | CZipActionCallback::cbCalculateForMulti);
    zip.Open(_T("C:\\Temp\\test.zip"), CZipArchive::zipCreate);    
    // add multiple files
    zip.AddNewFiles(_T("C:\\Temp"), _T("*.bin"), false);
    zip.Close();
}

See Also API Links

Article ID: 0610231200
Copyright © 2000 - 2009 Artpol Software - Tadeusz Dracz