|
// 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.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.