Click here to Skip to main content
11,490,801 members (73,796 online)
Click here to Skip to main content
Add your own
alternative version

CDirectoryChangeWatcher - ReadDirectoryChangesW all wrapped up

, 11 May 2002 904.5K 30.4K 343
This class wraps up ReadDirectoryChangesW.
cdirectorychangewatcher-05-12-2002_demo.zip
DirWatcher.dsp
DirWatcher.dsw
DirWatcher_ScreenShot2.jpg
SetFiltersDlg.jpg
TestPatterns.bmp
res
DirWatcher.ico
cdirectorychangewatcher-05-12-2002_src.zip
cdirectorychangewatcher-11-24-2001_src.zip
demowatcher.zip
DirWatcher.exe
DirWatcherU.exe
directorychangewatcher_demo.zip
DirWatcher.clw
DirWatcher.dsp
DirWatcher.dsw
DirWatcher.ico
DirWatcher.exe
directorychangewatcher_src.zip
dirwatcher-11-24-2001_demo.zip
DirWatcher.ico
DirWatcher.dsp
DirWatcher.dsw
DirWatcher.exe
// DelayedDirectoryChangeHandler.cpp: implementation of the CDelayedDirectoryChangeHandler2 class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "DirectoryChanges.h"
#include "DelayedDirectoryChangeHandler.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

#define UWM_DELALAYED_DIRECTORY_NOTIFICATION (WM_APP+1024)
//
//CDelayedDirectoryChangeNotification member functions:
//
CDelayedDirectoryChangeNotification::CDelayedDirectoryChangeNotification(CDelayedDirectoryChangeHandler *	pDelayedHandler)
:m_pDelayedHandler( pDelayedHandler )
,m_strFileName1()
,m_strFileName2()
,m_dwError(0UL)
{
	ASSERT( pDelayedHandler );
}

CDelayedDirectoryChangeNotification::~CDelayedDirectoryChangeNotification()
{
}
void CDelayedDirectoryChangeNotification::DispatchNotificationFunction()
{

	ASSERT( m_pDelayedHandler );
	if( m_pDelayedHandler )
		m_pDelayedHandler->DispatchNotificationFunction( this );
}

void CDelayedDirectoryChangeNotification::PostOn_FileAdded(const CString & strFileName)
{
	m_eFunctionToDispatch = eOn_FileAdded;
	m_strFileName1 = strFileName;
	//
	// post the message so it'll be dispatch by the main thread.
	PostNotification();

}
void CDelayedDirectoryChangeNotification::PostOn_FileRemoved(const CString & strFileName)
{
	m_eFunctionToDispatch = eOn_FileRemoved;
	m_strFileName1 = strFileName;
	//
	// post the message so it'll be dispatch by the main thread.
	PostNotification();
	
}
void CDelayedDirectoryChangeNotification::PostOn_FileNameChanged(const CString & strOldName, const CString & strNewName)
{
	m_eFunctionToDispatch = eOn_FileRenamed;
	m_strFileName1 = strOldName;
	m_strFileName2 = strNewName;
	//
	// post the message so it'll be dispatch by the main thread.
	PostNotification();
	
}

void CDelayedDirectoryChangeNotification::PostOn_FileModified(const CString & strFileName)
{
	m_eFunctionToDispatch = eOn_FileModified;
	m_strFileName1 = strFileName;
	//
	// post the message so it'll be dispatch by the main thread.
	PostNotification();
}

void CDelayedDirectoryChangeNotification::PostOn_ReadDirectoryChangesError(DWORD dwError)
{
	m_eFunctionToDispatch = eOn_ReadDirectoryChangesError;
	m_dwError = dwError;
	//
	// post the message so it'll be dispatch by the main thread.
	PostNotification();
	
}

void CDelayedDirectoryChangeNotification::PostNotification()
{
	ASSERT( m_pDelayedHandler );
	if( m_pDelayedHandler )
		m_pDelayedHandler->m_DelayWindow.PostNotification( this );
}


static LRESULT CALLBACK DelayedNotificationWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
//
//	This is the wndproc for the notification window
//
//	it's here to dispatch the notifications to the client
//
{
	if( message == UWM_DELALAYED_DIRECTORY_NOTIFICATION )
	{
		CDelayedDirectoryChangeNotification * pNotification = reinterpret_cast<CDelayedDirectoryChangeNotification*>(lParam);
		ASSERT(  pNotification );
		if( pNotification )
		{
			pNotification->DispatchNotificationFunction();
		}
		
		return 0UL;
	}
	else
		return DefWindowProc(hWnd,message,wParam,lParam);
}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//
//CDelayedDirectoryChangeNotification::CDelayedNotificationWindow static member vars:
//
long CDelayedDirectoryChangeHandler::CDelayedNotificationWindow::s_nRefCnt = 0L;
HWND CDelayedDirectoryChangeHandler::CDelayedNotificationWindow::s_hWnd = NULL;
BOOL CDelayedDirectoryChangeHandler::CDelayedNotificationWindow::s_bRegisterWindow = FALSE;
//
//
long CDelayedDirectoryChangeHandler::CDelayedNotificationWindow::AddRef()//creates window for first time if necessary
{
	if( InterlockedIncrement(&s_nRefCnt) == 1
		||	!::IsWindow( s_hWnd ) )
	{
		TRACE(_T("CDelayedDirectoryChangeHandler::CDelayedNotificationWindow -- Creating the notification window\n"));
		VERIFY( CreateNotificationWindow() );
	}
	return s_nRefCnt;
}

long CDelayedDirectoryChangeHandler::CDelayedNotificationWindow::Release()//destroys window for last time if necessary
{
	long nRefCnt = -1;
	if( (nRefCnt = InterlockedDecrement(&s_nRefCnt)) == 0 )
	{
		//no body else using the window so destroy it?
		TRACE(_T("CDelayedDirectoryChangeHandler::CDelayedNotificationWindow -- Destroying the notification window\n"));
		DestroyWindow( s_hWnd );
		s_hWnd = NULL;
	}
	return nRefCnt;
}
BOOL CDelayedDirectoryChangeHandler::CDelayedNotificationWindow::RegisterWindowClass(LPCTSTR szClassName)
//
//	registers our own window class to use as the hidden notification window.
//
{
	WNDCLASS wc = {0};
	
	wc.style = 0;
	wc.hInstance		= AfxGetInstanceHandle();
	wc.lpszClassName	= szClassName;
	wc.hbrBackground	= (HBRUSH)GetStockObject( WHITE_BRUSH );
	wc.lpfnWndProc		= DelayedNotificationWndProc;
	
	ATOM ant = RegisterClass( &wc );
	if( ant == NULL )
	{
		TRACE(_T("CDelayedDirectoryChangeNotification::RegisterWindowClass - RegisterClass failed: %d\n"), GetLastError());
	}
	return (BOOL)(ant!= NULL);
	
}

BOOL CDelayedDirectoryChangeHandler::CDelayedNotificationWindow::CreateNotificationWindow()
//
//	Create the hidden notification windows.
//
{
	TCHAR szClassName[] = _T("Delayed_Message_Sender");
	if( !s_bRegisterWindow )
		s_bRegisterWindow = RegisterWindowClass(szClassName);
	s_hWnd 	= CreateWindowEx(0, szClassName, _T("DelayedWnd"),0,0,0,0,0, NULL, 0, 
		AfxGetInstanceHandle(), NULL);
	if( s_hWnd == NULL )
	{
		TRACE(_T("Unable to create notification window! GetLastError(): %d\n"), GetLastError());
		TRACE(_T("File: %s Line: %d\n"), _T(__FILE__), __LINE__);
	}
	
	return (BOOL)(s_hWnd != NULL);
}
void CDelayedDirectoryChangeHandler::CDelayedNotificationWindow::PostNotification(CDelayedDirectoryChangeNotification * pNotification)
//
//	Posts a message to a window created in the main 
//	thread.
//	The main thread catches this message, and dispatches it in 
//	the context of the main thread.
//
{
	ASSERT( pNotification );
	ASSERT( s_hWnd );
	ASSERT( ::IsWindow( s_hWnd ) );

	PostMessage(s_hWnd, 
				UWM_DELALAYED_DIRECTORY_NOTIFICATION, 
				0, 
				reinterpret_cast<LPARAM>( pNotification ));

//  if you don't want the notification delayed, 
//  
//	if( false )
//	{
//		pNotification->DispatchNotificationFunction();
//	}
}
///////////////////////////////////////////////////////
//construction destruction
CDelayedDirectoryChangeHandler::CDelayedDirectoryChangeHandler(CDirectoryChangeHandler * pRealHandler)
: m_DelayWindow()
 ,m_pRealHandler( pRealHandler )
{
	ASSERT( m_pRealHandler );
}

CDelayedDirectoryChangeHandler::~CDelayedDirectoryChangeHandler()
{
}


CDelayedDirectoryChangeNotification * CDelayedDirectoryChangeHandler::GetNotificationObject()
//
//	Maybe in future I'll keep a pool of these 
//	objects around to increase performance...
//	using objects from a cache will be faster 
//	than allocated and destroying a new one each time.
//	
//  
{
	ASSERT( m_pRealHandler );
	return new CDelayedDirectoryChangeNotification(this);
}

void CDelayedDirectoryChangeHandler::DisposeOfNotification(CDelayedDirectoryChangeNotification * pNotification)
{
	delete pNotification;
}

//These functions are called when the directory to watch has had a change made to it
void CDelayedDirectoryChangeHandler::On_FileAdded(const CString & strFileName)
{
	CDelayedDirectoryChangeNotification * p = GetNotificationObject();
	ASSERT( p );
	if( p )
		p->PostOn_FileAdded( strFileName );
}

void CDelayedDirectoryChangeHandler::On_FileRemoved(const CString & strFileName)
{
	CDelayedDirectoryChangeNotification * p = GetNotificationObject();
	ASSERT( p );
	if( p )
		p->PostOn_FileRemoved( strFileName );
}

void CDelayedDirectoryChangeHandler::On_FileModified(const CString & strFileName)
{
	CDelayedDirectoryChangeNotification * p = GetNotificationObject();
	ASSERT( p );
	if( p )
		p->PostOn_FileModified( strFileName );
}

void CDelayedDirectoryChangeHandler::On_FileNameChanged(const CString & strOldFileName, const CString & strNewFileName)
{
	CDelayedDirectoryChangeNotification * p = GetNotificationObject();	
	ASSERT( p );
	if( p )
		p->PostOn_FileNameChanged( strOldFileName, strNewFileName );
}

void CDelayedDirectoryChangeHandler::On_ReadDirectoryChangesError(DWORD dwError)
{
	CDelayedDirectoryChangeNotification * p = GetNotificationObject();
	ASSERT( p );
	if( p )
		p->PostOn_ReadDirectoryChangesError( dwError );
}

void CDelayedDirectoryChangeHandler::DispatchNotificationFunction(CDelayedDirectoryChangeNotification * pNotification)
/*****************************************************
	This function is called when we want the notification to execute.

	
******************************************************/
{
	ASSERT( m_pRealHandler );
	ASSERT( pNotification );
	if( pNotification && m_pRealHandler )
	{
		switch( pNotification->m_eFunctionToDispatch )
		{
		case CDelayedDirectoryChangeNotification::eOn_FileAdded:
			
			m_pRealHandler->On_FileAdded( pNotification->m_strFileName1 ); 
			break;
			
		case CDelayedDirectoryChangeNotification::eOn_FileRemoved:
			
			m_pRealHandler->On_FileRemoved( pNotification->m_strFileName1 );
			break;
			
		case CDelayedDirectoryChangeNotification::eOn_FileRenamed:
			
			m_pRealHandler->On_FileNameChanged( pNotification->m_strFileName1, pNotification->m_strFileName2 );
			break;
			
		case CDelayedDirectoryChangeNotification::eOn_FileModified:
			
			m_pRealHandler->On_FileModified( pNotification->m_strFileName1 );
			break;
			
		case CDelayedDirectoryChangeNotification::eOn_ReadDirectoryChangesError:
			
			m_pRealHandler->On_ReadDirectoryChangesError( pNotification->m_dwError );
			break;
			
		case CDelayedDirectoryChangeNotification::eFunctionNotDefined:
		default:
			break;
		}
		
		//
		// deletes or releases the notification object from memory/use
		//
		DisposeOfNotification(pNotification);
	}	
}

void CDelayedDirectoryChangeHandler::SetChangedDirectoryName(const CString & strChangedDirName)
{
	ASSERT( m_pRealHandler );
	CDirectoryChangeHandler::SetChangedDirectoryName(strChangedDirName);
	if( m_pRealHandler )
		m_pRealHandler->SetChangedDirectoryName( strChangedDirName );
}
const CString & CDelayedDirectoryChangeHandler::GetChangedDirectoryName() const
{
	if( m_pRealHandler )
		return m_pRealHandler->GetChangedDirectoryName();
	return CDirectoryChangeHandler::GetChangedDirectoryName();
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

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

Share

About the Author

Wes Jones
Web Developer
United States United States
No Biography provided

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.150520.1 | Last Updated 12 May 2002
Article Copyright 2001 by Wes Jones
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid