Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

CFileChangeEvent Class

0.00/5 (No votes)
30 Nov 1999 1  
An article about how we can notify our application that a file has been changed by another application.

Introduction

This article is about how we can notify our application that a file has been changed by another application.

I've created the CFileChangeEvent-class for it. It has the following methods:

void addFile(const std::string &sFileName)
Use this method when you want to be notified of changes of a file. When the notification thread is running, it will be stopped and restarted.
void removeFile(const std::string &sFileName)
Use this method when you don't want to be notified anymore. When the notification thread is running, it will be stopped and restarted.
void startWatch(void)
This method starts the notification thread.
void stopWatch(void)
This method stops the notification thread. It's also called in the destructor, so you know the thread will always stop.
virtual void OnFileAlarm(FileAlarm nAlarm, const std::string &sFileName)

Override this method. This method is called when a file is changed or deleted. FileAlarm is an enum with following attributes: FA_CHANGED, FA_REMOVED, FA_CREATED.

How to use this class ?

Derive a class (for example your CDocument-class) from CFileChangeEvent and override the OnFileAlarm. That's all.

Warning: You can't call the method UpdateAllViews in the OnFileAlarm. This is why:

A thread can access only MFC objects that it created. This is because temporary and permanent Windows handle maps are kept in thread local storage to ensure protection from simultaneous access from multiple threads.

How can we solve this?

  1. Pass the individual handles (like HWND) rather than C++ objects, to the worker thread. The thread then adds these objects to its temporary map by calling the appropriate FromHandle member function.
  2. You can use a new user-defined message corresponding to the different tasks your worker threads will be performing and post these messages to the application's windows/views using PostMessage.
    1. Create a user-defined message with ::RegisterWindowMessage like this:
      const UINT msgFileChange = ::RegisterWindowMessage("FILECHANGE");

      Put this in the application's header file so that you can use this everywhere in your application

    2. In your document-class, create a member-variable to hold a pointer to the window you want to process the message.
      CView *m_pView;
      // This variable must be initialized in your view-class.
    3. In the method called by the thread, post the message to the processing window.
      // You can pass wparam, lparam if you wish
      
      m_pView->PostMessage(msgFileChange);
    4. In the processing view header file, add the following in the message map functions:
      // when you pass wparam, lparam add parameters to this function
      
      afx_msg void OnFileChange();
    5. In the processing view source file, add the following in the message map:
      ON_REGISTERED_MESSAGE(msgFileChange, OnFileChange)
    6. Add the source code for OnFileChange in the processing view source file.
      void CProcessView::OnFileChange()
      {
          CMyDocument *pDoc = GetDocument();
          pDoc->UpdateAllViews();
      }

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here