How to copy or move file with progress?

28 08 2008

In old Win98 days, File copying progress notification was horrific. Even if you have a lot of data to copy, it always says – you have 5 more minutes to finish. 😀 Well, how to copy or move file with accurate progress?

You can use the api – CopyFileEx() for copying data with progress and MoveFileEx() to move files with progress. Both are more or less similar in usage. In both cases, just call the apis by providing the callback function pointer. System will give callback notification for the progress. See the code snippet of CopyFileEx().

// Callback function for handling progress notification.
DWORD CALLBACK CopyProgressRoutine(
                          LARGE_INTEGER TotalFileSize,
                          LARGE_INTEGER TotalBytesTransferred,
                          LARGE_INTEGER StreamSize,
                          LARGE_INTEGER StreamBytesTransferred,
                          DWORD dwStreamNumber,
                          DWORD dwCallbackReason,
                          HANDLE hSourceFile,
                          HANDLE hDestinationFile,
                          LPVOID lpData )
    // Calculate the percentage here.
    double Percentage = ( double(TotalBytesTransferred.QuadPart) /
        double(TotalFileSize.QuadPart) ) * 100;

    // Continue the file copy. It can also be stopped.

void CDlgDlg::OnCopy()
    // Copy the file.
    CopyFileEx( _T("c:\\Jijo\\Games.rar"),
                0 );

CopyFIleEx() and MoveFileEx() are available only from Windows NT onwards. So don’t forget to add _WIN32_WINNT=0x0400 to project settings.

Targeted Audience – Beginners.

How to get the File/Directory change notifications?

11 06 2008

Usually projects have several settings stored in configuration files and in some special cases, the configuration can change at runtime and the changes should reflect instantaneously. How it can be done? Well, it can be done with the help of a timer and reload the configuration every 5 seconds. Or is there another smarter api? 😉

Yep! you can use – ReadDirectoryChangesW(). It can be called synchronously as well as asynchronously. If its called in synchronous the calling thread will be in blocking state and return only if any file change is detected. See the code snippet for calling it synchronously.

// Directory to watch.
CString csDirectory = _T("C:\\Config");
HANDLE hDirectory = CreateFile( csDirectory,
                              NULL );

// Buffer to get the notification information.
const int MAX_BUFFER = 1024;
DWORD dwBytesReturned = 0;
ReadDirectoryChangesW( hDirectory,
                     0 );

// Cast the buffer as Notification Struct.

// Changed file.
CString csFileName = pNotifyInfo->FileName;

You can give watch filters via dwNotifyFilter parameter. So that you can watch for specific events such as filename change, new file creation, file size change etc.

The interesting part is – unlike other api’s, ReadDirectoryChangesW() have unicode version only. So don’t forget to add UNICODE and _UNICODE to your project settings. At first if you try to compile it, most probably you’ll hit the following error.

error C2065: 'ReadDirectoryChangesW' : undeclared identifier

For fixing this add _WIN32_WINNT=0x0400 to the preprocessor settings in C/C++ tab of project settings. I hope you understand – why. 😉

Targeted Audience – Intermediate.