?? filewatch.cpp
字號:
// FileWatch.cpp: implementation of the CFileWatch class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "FileWatchApp.h"
#include "FileWatch.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
CString GetLastErrorMsg()
{
DWORD nError = GetLastError();
LPVOID lpMsgBuf;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, nError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL );
CString str = (LPCTSTR)lpMsgBuf;
LocalFree(lpMsgBuf);
return str;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CMap<DWORD,DWORD&,FILEWATCHITEM,FILEWATCHITEM&> CFileWatch::m_FileMap;
CList<CString,CString&> CFileWatch::m_FolderList;
CList<HANDLE,HANDLE&> CFileWatch::m_NotifyList;
CEvent CFileWatch::m_ClassEvent;
DWORD CFileWatch::m_dwNextHandle = 1;
bool CFileWatch::m_bWatchClosed = true;
bool CFileWatch::m_bStopWatch = false;
void CFileWatch::Start()
{
m_bStopWatch = false;
m_ClassEvent.SetEvent();
AfxBeginThread(Watch, NULL, THREAD_PRIORITY_LOWEST);
m_bWatchClosed = false;
}
void CFileWatch::Stop()
{
m_bStopWatch = true;
m_ClassEvent.SetEvent();
while (!m_bWatchClosed)
Sleep(100);
TRACE("stop\n");
}
bool GetLastWriteTime(LPCTSTR lpszFileName, __int64 &ftLastWriteTime)
{
CFile file;
if (!file.Open(lpszFileName, CFile::shareDenyNone))
return false;
BY_HANDLE_FILE_INFORMATION info;
if (!GetFileInformationByHandle((HANDLE)file.m_hFile, &info))
return false;
ftLastWriteTime = (__int64(info.ftLastWriteTime.dwHighDateTime)<<32) + info.ftLastWriteTime.dwLowDateTime;
return true;
}
CString GetFolder(LPCTSTR lpszFileName)
{
TCHAR szDrive[_MAX_DRIVE], szDir[_MAX_DIR];
_tsplitpath(lpszFileName, szDrive, szDir, NULL, NULL);
return CString(szDrive) + CString(szDir);
}
DWORD CFileWatch::AddFileFolder(LPCTSTR lpszFileName, HWND hWnd, CDocument* pDocument, DWORD dwData)
{
CString sFolder = GetFolder(lpszFileName);
bool bIsFolder = sFolder == lpszFileName;
__int64 ftLastWriteTime;
if (!bIsFolder && !GetLastWriteTime(lpszFileName, ftLastWriteTime))
return 0;
FILEWATCHITEM fwItem;
fwItem.sFileName = lpszFileName;
fwItem.ftLastWriteTime = ftLastWriteTime;
fwItem.hWnd = hWnd;
fwItem.pDocument = pDocument;
fwItem.dwData = dwData;
fwItem.bIsFolder = bIsFolder;
DWORD dwHandle = m_dwNextHandle++;
m_FileMap.SetAt(dwHandle, fwItem);
// new directory to watch?
if (!m_FolderList.Find(sFolder))
{
HANDLE hChangeNotification = FindFirstChangeNotification(sFolder, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_LAST_WRITE);
ASSERT(hChangeNotification != INVALID_HANDLE_VALUE);
m_FolderList.AddTail(sFolder);
m_NotifyList.AddTail(hChangeNotification);
}
m_ClassEvent.SetEvent();
if (CFileWatch::m_bWatchClosed)
Start();
return dwHandle;
}
void CFileWatch::ResetDate(DWORD dwHandle)
{
FILEWATCHITEM fwItem;
if (!m_FileMap.Lookup(dwHandle, fwItem))
return;
CString sFolder = GetFolder(fwItem.sFileName);
__int64 ftLastWriteTime;
if (GetLastWriteTime(fwItem.sFileName, ftLastWriteTime))
{
fwItem.ftLastWriteTime = ftLastWriteTime;
m_FileMap.SetAt(dwHandle, fwItem);
}
}
void CFileWatch::RemoveHandle(DWORD dwHandle)
{
FILEWATCHITEM fwItem;
if (!m_FileMap.Lookup(dwHandle, fwItem))
return;
m_FileMap.RemoveKey(dwHandle);
CString sFolder = GetFolder(fwItem.sFileName);
bool bDeleteDir = true;
POSITION pos = m_FileMap.GetStartPosition();
while (pos)
{
DWORD dwHandle;
FILEWATCHITEM fwItem;
if (GetFolder(fwItem.sFileName) == sFolder)
{
bDeleteDir = false;
break;
}
m_FileMap.GetNextAssoc(pos, dwHandle, fwItem);
}
if (bDeleteDir)
{
POSITION pos = m_FolderList.Find(sFolder);
int nIndex = 0;
while (pos != m_FolderList.FindIndex(nIndex))
nIndex++;
m_FolderList.RemoveAt(pos);
pos = m_NotifyList.FindIndex(nIndex);
FindCloseChangeNotification(m_NotifyList.GetAt(pos));
m_NotifyList.RemoveAt(pos);
}
if (m_FileMap.IsEmpty())
Stop();
}
UINT CFileWatch::Watch(LPVOID lpParam)
{
CArray<HANDLE,HANDLE> arHandle;
arHandle.Add(m_ClassEvent);
for (;;)
{
// wait for event or notification
DWORD dwResult = WaitForMultipleObjects(arHandle.GetSize(), arHandle.GetData(), FALSE, INFINITE);
if (m_bStopWatch)
break;
int nObject = dwResult - WAIT_OBJECT_0;
if (nObject==0)
{
// refresh list
arHandle.SetSize(1);
POSITION pos = m_NotifyList.GetHeadPosition();
while (pos)
arHandle.Add(m_NotifyList.GetNext(pos));
m_ClassEvent.ResetEvent();
}
else if (nObject>0 && nObject<arHandle.GetSize())
{
CString sFolder = m_FolderList.GetAt(m_FolderList.FindIndex(nObject-1));
POSITION pos = m_FileMap.GetStartPosition();
while (pos)
{
DWORD dwHandle;
FILEWATCHITEM fwItem;
m_FileMap.GetNextAssoc(pos, dwHandle, fwItem);
if (GetFolder(fwItem.sFileName) == sFolder)
{
__int64 ftLastWriteTime;
if (fwItem.bIsFolder || GetLastWriteTime(fwItem.sFileName, ftLastWriteTime))
{
if (fwItem.bIsFolder || fwItem.ftLastWriteTime!=ftLastWriteTime)
{
TRACE("%s\n",fwItem.sFileName);
HWND hWnd = fwItem.hWnd;
if (fwItem.pDocument)
{
POSITION pos = fwItem.pDocument->GetFirstViewPosition();
CView *pView = fwItem.pDocument->GetNextView(pos);
hWnd = pView->GetSafeHwnd();
}
if (hWnd)
::PostMessage(hWnd, WM_FILEWATCH_NOTIFY, WPARAM(fwItem.dwData), LPARAM(LPCTSTR(fwItem.sFileName)));
fwItem.ftLastWriteTime = ftLastWriteTime;
m_FileMap.SetAt(dwHandle, fwItem);
}
}
}
}
}
}
// clean up
POSITION pos = m_NotifyList.GetHeadPosition();
while (pos)
FindCloseChangeNotification(m_NotifyList.GetNext(pos));
m_NotifyList.RemoveAll();
m_FolderList.RemoveAll();
m_FileMap.RemoveAll();
TRACE("thread stopped\n");
m_bWatchClosed = true;
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -