You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
295 lines
6.9 KiB
C++
295 lines
6.9 KiB
C++
// XTPDirWatcher.cpp : implementation file
|
|
//
|
|
// This file is a part of the XTREME CONTROLS MFC class library.
|
|
// (c)1998-2012 Codejock Software, All Rights Reserved.
|
|
//
|
|
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
|
|
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
|
|
// CONSENT OF CODEJOCK SOFTWARE.
|
|
//
|
|
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
|
|
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
|
|
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
|
|
// SINGLE COMPUTER.
|
|
//
|
|
// CONTACT INFORMATION:
|
|
// support@codejock.com
|
|
// http://www.codejock.com
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "Common/XTPVC80Helpers.h" // Visual Studio 2005 helper functions
|
|
|
|
#include "../Defines.h"
|
|
#include "XTPShellPidl.h"
|
|
#include "XTPDirWatcher.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CXTPDirWatcher
|
|
|
|
CXTPDirWatcher::CXTPDirWatcher()
|
|
{
|
|
m_bWatchSubtree = FALSE;
|
|
m_bAutoDelete = TRUE;
|
|
m_dwMonitorEvents[0] = INVALID_HANDLE_VALUE;
|
|
m_dwMonitorEvents[1] = INVALID_HANDLE_VALUE;
|
|
m_dwMonitorEvents[2] = CreateEvent(NULL, TRUE, FALSE, 0); // Path was changed event.
|
|
m_dwMonitorEvents[3] = CreateEvent(NULL, TRUE, FALSE, 0); // Stop notifications event.
|
|
|
|
ZeroMemory(&m_tvid, sizeof(m_tvid));
|
|
}
|
|
|
|
CXTPDirWatcher::~CXTPDirWatcher()
|
|
{
|
|
CloseHandle(m_dwMonitorEvents[2]);
|
|
CloseHandle(m_dwMonitorEvents[3]);
|
|
}
|
|
|
|
void CXTPDirWatcher::StopNotifications()
|
|
{
|
|
SetEvent(m_dwMonitorEvents[3]);
|
|
WaitForSingleObject(m_hThread, INFINITE);
|
|
}
|
|
|
|
|
|
IMPLEMENT_DYNCREATE(CXTPDirWatcher, CWinThread)
|
|
|
|
BEGIN_MESSAGE_MAP(CXTPDirWatcher, CWinThread)
|
|
//{{AFX_MSG_MAP(CXTPDirWatcher)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
BOOL CXTPDirWatcher::WaitPathChangedEvent()
|
|
{
|
|
DWORD dw = ::WaitForMultipleObjects(2,
|
|
&m_dwMonitorEvents[2], FALSE, INFINITE);
|
|
|
|
return dw != WAIT_OBJECT_0 + 1;
|
|
}
|
|
|
|
BOOL CXTPDirWatcher::MonitorNotifications()
|
|
{
|
|
BOOL bContinueThread = TRUE;
|
|
|
|
::ResetEvent(m_dwMonitorEvents[2]);
|
|
::ResetEvent(m_dwMonitorEvents[3]);
|
|
|
|
if (!IsPathValid(m_strFolderPath))
|
|
return WaitPathChangedEvent();
|
|
|
|
// Watch the directory for file creation and
|
|
// deletion.
|
|
|
|
m_dwMonitorEvents[0] = ::FindFirstChangeNotification(
|
|
m_strFolderPath, // directory to watch
|
|
m_bWatchSubtree, // monitor the subtree
|
|
FILE_NOTIFY_CHANGE_FILE_NAME); // watch file name changes
|
|
|
|
if (m_dwMonitorEvents[0] == INVALID_HANDLE_VALUE)
|
|
return WaitPathChangedEvent();
|
|
|
|
// Watch the tree for directory creation and
|
|
// deletion.
|
|
|
|
m_dwMonitorEvents[1] = ::FindFirstChangeNotification(
|
|
m_strFolderPath, // directory to watch
|
|
m_bWatchSubtree, // monitor the subtree
|
|
FILE_NOTIFY_CHANGE_DIR_NAME); // watch dir. name changes
|
|
|
|
if (m_dwMonitorEvents[1] == INVALID_HANDLE_VALUE)
|
|
return WaitPathChangedEvent();
|
|
|
|
// Change notification is set. Now wait on both notification
|
|
// handles and refresh accordingly.
|
|
|
|
BOOL bConinueNotifications = TRUE;
|
|
|
|
while (bConinueNotifications)
|
|
{
|
|
// Wait for notification.
|
|
|
|
DWORD dwWaitStatus = ::WaitForMultipleObjects(_countof(m_dwMonitorEvents),
|
|
m_dwMonitorEvents, FALSE, INFINITE);
|
|
|
|
|
|
switch (dwWaitStatus)
|
|
{
|
|
case WAIT_OBJECT_0:
|
|
|
|
// A file was created or deleted in C:\WINDOWS.
|
|
// Refresh this directory and restart the
|
|
// change notification. RefreshDirectory is an
|
|
// application-defined function.
|
|
|
|
RefreshFolder();
|
|
|
|
if (!::FindNextChangeNotification(m_dwMonitorEvents[0]))
|
|
bConinueNotifications = FALSE;
|
|
|
|
if (!IsPathValid(m_strFolderPath))
|
|
bConinueNotifications = FALSE;
|
|
|
|
break;
|
|
|
|
case WAIT_OBJECT_0 + 1:
|
|
|
|
// A directory was created or deleted in C:\.
|
|
// Refresh the directory tree and restart the
|
|
// change notification. RefreshTree is an
|
|
// application-defined function.
|
|
|
|
RefreshTree();
|
|
|
|
if (!::FindNextChangeNotification(m_dwMonitorEvents[1]))
|
|
bConinueNotifications = FALSE;
|
|
|
|
if (!IsPathValid(m_strFolderPath))
|
|
bConinueNotifications = FALSE;
|
|
|
|
break;
|
|
|
|
case WAIT_OBJECT_0 + 2:
|
|
bContinueThread = TRUE;
|
|
bConinueNotifications = FALSE;
|
|
break;
|
|
|
|
case WAIT_OBJECT_0 + 3:
|
|
bContinueThread = FALSE;
|
|
bConinueNotifications = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Close the file change notification handle and return.
|
|
::FindCloseChangeNotification (m_dwMonitorEvents[0]);
|
|
::FindCloseChangeNotification (m_dwMonitorEvents[1]);
|
|
|
|
m_dwMonitorEvents[0] = INVALID_HANDLE_VALUE;
|
|
m_dwMonitorEvents[1] = INVALID_HANDLE_VALUE;
|
|
|
|
return bContinueThread;
|
|
}
|
|
|
|
BOOL CXTPDirWatcher::InitInstance()
|
|
{
|
|
BOOL bContinueThread = TRUE;
|
|
|
|
while (bContinueThread)
|
|
{
|
|
bContinueThread = MonitorNotifications();
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CXTPDirWatcher::IsPathValid(LPCTSTR lpszFolderPath)
|
|
{
|
|
if (_tcslen(lpszFolderPath) == 0)
|
|
return FALSE;
|
|
|
|
if (!DIRECTORYEXISTS_S(lpszFolderPath))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CXTPDirWatcher::SetFolderPath(CWnd* pMainWnd, LPCTSTR lpszFolderPath, BOOL bWatchSubtree)
|
|
{
|
|
if (IsPathValid(lpszFolderPath))
|
|
{
|
|
if (GetFolderData(lpszFolderPath, m_tvid))
|
|
{
|
|
m_pMainWnd = pMainWnd;
|
|
m_strFolderPath = lpszFolderPath;
|
|
m_bWatchSubtree = bWatchSubtree;
|
|
|
|
SetEvent(m_dwMonitorEvents[2]); // Folder was changed event
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CXTPDirWatcher::SetFolderData(CWnd* pMainWnd, XTP_TVITEMDATA* lpTVID)
|
|
{
|
|
if (!lpTVID)
|
|
return FALSE;
|
|
|
|
TCHAR szFolderPath[_MAX_PATH];
|
|
if (::SHGetPathFromIDList(lpTVID->lpifq, szFolderPath))
|
|
{
|
|
return SetFolderPath(pMainWnd, szFolderPath);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CXTPDirWatcher::GetFolderData(LPCTSTR lpszFolderPath, XTP_TVITEMDATA& lpTVID)
|
|
{
|
|
LPITEMIDLIST pidl;
|
|
LPSHELLFOLDER pDesktopFolder;
|
|
OLECHAR szOleChar[MAX_PATH];
|
|
ULONG chEaten;
|
|
ULONG dwAttributes;
|
|
|
|
if (!IsPathValid(lpszFolderPath))
|
|
return FALSE;
|
|
|
|
// Get a pointer to the Desktop's IShellFolder interface.
|
|
if (SUCCEEDED(::SHGetDesktopFolder(&pDesktopFolder)))
|
|
{
|
|
// IShellFolder::ParseDisplayName requires the file name be in
|
|
// Unicode.
|
|
|
|
#if !defined(_UNICODE)
|
|
::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpszFolderPath, -1,
|
|
szOleChar, MAX_PATH);
|
|
#else
|
|
STRCPY_S(szOleChar, MAX_PATH, lpszFolderPath);
|
|
#endif
|
|
|
|
// Convert the path to an ITEMIDLIST.
|
|
if (SUCCEEDED(pDesktopFolder->ParseDisplayName(NULL, NULL, szOleChar,
|
|
&chEaten, &pidl, &dwAttributes)))
|
|
{
|
|
IShellFolder *psfMyFolder;
|
|
|
|
lpTVID.lpi = lpTVID.lpifq = pidl;
|
|
|
|
pDesktopFolder->BindToObject(lpTVID.lpifq, NULL,
|
|
IID_IShellFolder, (LPVOID*)&psfMyFolder);
|
|
|
|
lpTVID.lpsfParent = psfMyFolder;
|
|
pDesktopFolder->Release();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
pDesktopFolder->Release();
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void CXTPDirWatcher::RefreshFolder()
|
|
{
|
|
m_pMainWnd->SendMessage(WM_XTP_SHELL_NOTIFY,
|
|
SHN_XTP_REFRESHFOLDER, (LPARAM)&m_tvid);
|
|
}
|
|
|
|
void CXTPDirWatcher::RefreshTree()
|
|
{
|
|
m_pMainWnd->SendMessage(WM_XTP_SHELL_NOTIFY,
|
|
SHN_XTP_REFRESHTREE, (LPARAM)&m_tvid);
|
|
}
|