Click here to Skip to main content
15,885,875 members
Articles / Desktop Programming / MFC
Article

The Ultimate Toolbox File Watcher

Rate me:
Please Sign up or sign in to vote.
4.68/5 (5 votes)
25 Aug 2007CPOL3 min read 43.7K   1.6K   25   4
An easy to use file watcher from the Ultimate Toolbox

Visit the Ultimate Toolbox main page for an overview and configuration guide to the Ultimate Toolbox library.

Source code and project files for this sample can be found in the samples\file\FileWatcher directory of the sample projects download.

Overview

Image 1

The class COXFileWatcher organizes file change notifications in a number of directories supplied by the user. All notifications are handled by a virtual function, which can be overridden in the derived class. The class can also convert these events to window messages. Examples of notifications are: file creation, file deletion, creation of a new directory, file size change, attribute change etc.

Features

  • Easy to use in your application (just create a variable).
  • The number of watched directories is limited only by the available memory.
  • Directories can be added for watching or removed from the watch list at any time.
  • Different types of watch filters can be supplied.
  • The control can watch a specified directory or the whole directory tree.
  • Different approaches for handling the change notifications are possible (via a virtual function or a Windows message).
  • Extra info for each type of change that may occur in the watched directories (only available on Windows NT 4.0 or newer).
  • Runs in its own thread, so your application may continue its work.

Usage

There are two approaches in using the COXFileWatcher class. These depend on how you choose to handle the notifications:

  1. The first approach is to derive a class from COXFileWatcher and override the following function:
C++
virtual BOOL OnNotify(COXFileWatchNotifier fileWatchNotifier)

This function is called when a file change notification is received by the file watch object. The function receives a copy of the received parameters in the form of a COXFileWatchNotifier object. The return value indicates whether this notification should be ignored (TRUE) or whether the object may continue handling the event (FALSE). The last option (FALSE) is necessary if the event is to be translated into a window message.

  1. The second method involves instantiating a COXFileWatcher object and associating the watched directories with a window (EnableWindowNotification()). This window will then receive the WM_OX_FILE_NOTIFY message with information about file change notifications. (The WPARAM contains an index (nItemIndex) which can be linked to a COXFileWatchNotifier object (see below) through a call to the function GetFileWatchNotifier()).

    In either the first or second case the easiest way to use the class is to create an instance of the class COXFileWatcher or of the derived one. Then a directory can be supplied for watching with a call to the following function:
C++
BOOL AddWatch(LPCTSTR pszPath, BOOL bWatchSubtree = FALSE, 
    DWORD nWatchFilter = OXFileWatchChangeFileName | 
    OXFileWatchChangeLastWrite);

The FileWatcher sample implements the second approach.

First a COXFileWatcher object is declared as a member of the class:

C++
#include "OXFileWatcher.h"

/////////////////////////////////////////////////////////////////////////////

// CFileWatcherDlg dialog

class CFileWatcherDlg : public CDialog
{
    COXFileWatcher    fwWatcher;

// Construction

public:
    ...

Next, a message handler is set up to trap notifications that will be sent to the dialog (after a call to EnableWindowNotifications):

C++
BEGIN_MESSAGE_MAP(CFileWatcherDlg, CDialog)
    //{{AFX_MSG_MAP(CFileWatcherDlg)

    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDC_ADD_DIR, OnAddDir)
    ON_BN_CLICKED(IDC_REMOVE_DIR, OnRemoveDir)
    ON_MESSAGE( WM_OX_FILE_NOTIFY, OnFileNotify )    // add this handler

    //}}AFX_MSG_MAP

And then the OnFileNotify function is added - in this case it extracts information from the object with which to populate the list:

C++
LRESULT CFileWatcherDlg::OnFileNotify(WPARAM wP, LPARAM)
// --- In  : wP: the ID of the Notifier object

// --- Out : 

// --- Returns : ...

// --- Effect : Responds to the notification message from FileWatcher

{
    CString str;

    COXFileWatchNotifier fwnNotifier;
    fwnNotifier = fwWatcher.GetFileWatchNotifier( wP);
    ...     // code removed //

    return 0;
}

Now all that's needed is to set up the file watcher with information on the files/directories to be tracked - the sample uses a dialog to glean this info then set it to the file watcher oblect:

C++
void CFileWatcherDlg::OnAddDir() 
// --- In  : 

// --- Out : 

// --- Returns : 

// --- Effect : Responds to the 'Add dir...' button

{
    CEnterNewDir dlg;
    CString str;

    // Gets the watched directory and filter

    if(dlg.DoModal() == IDOK)
    {
        if(!dlg.m_sDir.IsEmpty())
        {
            DWORD filter=0;

            // Determines the watch filter

            if( dlg.m_bChangeAttributes)
            {
                filter |= COXFileWatcher::OXFileWatchChangeAttributes;
            }
            if( dlg.m_bChangeCreation)
            {
                filter |= COXFileWatcher::OXFileWatchChangeCreation;
            }
            if( dlg.m_bChangeDirName)
            {
                filter |= COXFileWatcher::OXFileWatchChangeDirName;
            }
            if( dlg.m_bChangeFileName)
            {
                filter |= COXFileWatcher::OXFileWatchChangeFileName;
            }
            if( dlg.m_bChangeLastAccess)
            {
                filter |= COXFileWatcher::OXFileWatchChangeLastAccess;
            }
            if( dlg.m_bChangeLastWrite)
            {
                filter |= COXFileWatcher::OXFileWatchChangeLastWrite;
            }
            if( dlg.m_bChangeSecurity)
            {
                filter |= COXFileWatcher::OXFileWatchChangeSecurity;
            }
            if( dlg.m_bChangeSize)
            {
                filter |= COXFileWatcher::OXFileWatchChangeSize;
            }
            if( fwWatcher.AddWatch( dlg.m_sDir, dlg.m_bSubTree, filter))
            {
                // If the directory is added set the window for notifications

                fwWatcher.EnableWindowNotification( dlg.m_sDir, this, TRUE);
            ... // code removed

And the notification routine should now receive the desired notifications.

For more details, refer to the COXFileWatcher and COXFileWatchNotifier class references in the File Management | File Watch section of the compiled HTML help documentation, and the FileWatcher sample.

History

Initial CodeProject release August 2007.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Canada Canada
In January 2005, David Cunningham and Chris Maunder created TheUltimateToolbox.com, a new group dedicated to the continued development, support and growth of Dundas Software’s award winning line of MFC, C++ and ActiveX control products.

Ultimate Grid for MFC, Ultimate Toolbox for MFC, and Ultimate TCP/IP have been stalwarts of C++/MFC development for a decade. Thousands of developers have used these products to speed their time to market, improve the quality of their finished products, and enhance the reliability and flexibility of their software.
This is a Organisation

476 members

Comments and Discussions

 
QuestionHow to include OnFileNotify in the code Pin
Member 927486413-Sep-12 16:26
Member 927486413-Sep-12 16:26 
GeneralMy vote of 5 Pin
amit_myana20-Jul-11 20:01
amit_myana20-Jul-11 20:01 
GeneralNot running in my computer Pin
expertsudhir5-Feb-11 5:21
expertsudhir5-Feb-11 5:21 
Generalfile watcher + linux Pin
raphaelverdier11-Jun-09 2:37
raphaelverdier11-Jun-09 2:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.