XTDirWatcher.cpp
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:7k
源码类别:

对话框与窗口

开发平台:

Visual C++

  1. // XTDirWatcher.cpp : implementation file
  2. //
  3. // This file is a part of the XTREME CONTROLS MFC class library.
  4. // (c)1998-2008 Codejock Software, All Rights Reserved.
  5. //
  6. // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
  7. // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
  8. // CONSENT OF CODEJOCK SOFTWARE.
  9. //
  10. // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
  11. // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
  12. // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
  13. // SINGLE COMPUTER.
  14. //
  15. // CONTACT INFORMATION:
  16. // support@codejock.com
  17. // http://www.codejock.com
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include "Common/XTPVC80Helpers.h"  // Visual Studio 2005 helper functions
  22. #include "XTDefines.h"
  23. #include "XTShellPidl.h"
  24. #include "XTDirWatcher.h"
  25. #ifdef _DEBUG
  26. #define new DEBUG_NEW
  27. #undef THIS_FILE
  28. static char THIS_FILE[] = __FILE__;
  29. #endif
  30. /////////////////////////////////////////////////////////////////////////////
  31. // CXTDirWatcher
  32. CXTDirWatcher::CXTDirWatcher()
  33. {
  34. m_bAutoDelete = TRUE;
  35. m_dwMonitorEvents[0] = INVALID_HANDLE_VALUE;
  36. m_dwMonitorEvents[1] = INVALID_HANDLE_VALUE;
  37. m_dwMonitorEvents[2] = CreateEvent(NULL, TRUE, FALSE, 0);   // Path was changed event.
  38. m_dwMonitorEvents[3] = CreateEvent(NULL, TRUE, FALSE, 0);   // Stop notifications event.
  39. ZeroMemory(&m_tvid, sizeof(m_tvid));
  40. }
  41. CXTDirWatcher::~CXTDirWatcher()
  42. {
  43. CloseHandle(m_dwMonitorEvents[2]);
  44. CloseHandle(m_dwMonitorEvents[3]);
  45. }
  46. void CXTDirWatcher::StopNotifications()
  47. {
  48. SetEvent(m_dwMonitorEvents[3]);
  49. WaitForSingleObject(m_hThread, INFINITE);
  50. }
  51. IMPLEMENT_DYNCREATE(CXTDirWatcher, CWinThread)
  52. BEGIN_MESSAGE_MAP(CXTDirWatcher, CWinThread)
  53. //{{AFX_MSG_MAP(CXTDirWatcher)
  54. //}}AFX_MSG_MAP
  55. END_MESSAGE_MAP()
  56. BOOL CXTDirWatcher::WaitPathChangedEvent()
  57. {
  58. DWORD dw = ::WaitForMultipleObjects(2,
  59. &m_dwMonitorEvents[2], FALSE, INFINITE);
  60. return dw != WAIT_OBJECT_0 + 1;
  61. }
  62. BOOL CXTDirWatcher::MonitorNotifications()
  63. {
  64. BOOL bContinueThread = TRUE;
  65. ::ResetEvent(m_dwMonitorEvents[2]);
  66. ::ResetEvent(m_dwMonitorEvents[3]);
  67. if (!IsPathValid(m_strFolderPath))
  68. return WaitPathChangedEvent();
  69. // Watch the directory for file creation and
  70. // deletion.
  71. m_dwMonitorEvents[0] = ::FindFirstChangeNotification(
  72. m_strFolderPath, // directory to watch
  73. FALSE, // do not watch the subtree
  74. FILE_NOTIFY_CHANGE_FILE_NAME); // watch file name changes
  75. if (m_dwMonitorEvents[0] == INVALID_HANDLE_VALUE)
  76. return WaitPathChangedEvent();
  77. // Watch the tree for directory creation and
  78. // deletion.
  79. m_dwMonitorEvents[1] = ::FindFirstChangeNotification(
  80. m_strFolderPath, // directory to watch
  81. FALSE, // watch the subtree
  82. FILE_NOTIFY_CHANGE_DIR_NAME);  // watch dir. name changes
  83. if (m_dwMonitorEvents[1] == INVALID_HANDLE_VALUE)
  84. return WaitPathChangedEvent();
  85. // Change notification is set. Now wait on both notification
  86. // handles and refresh accordingly.
  87. BOOL bConinueNotifications = TRUE;
  88. while (bConinueNotifications)
  89. {
  90. // Wait for notification.
  91. DWORD dwWaitStatus = ::WaitForMultipleObjects(_countof(m_dwMonitorEvents),
  92. m_dwMonitorEvents, FALSE, INFINITE);
  93. switch (dwWaitStatus)
  94. {
  95. case WAIT_OBJECT_0:
  96. // A file was created or deleted in C:WINDOWS.
  97. // Refresh this directory and restart the
  98. // change notification. RefreshDirectory is an
  99. // application-defined function.
  100. RefreshFolder();
  101. if (!::FindNextChangeNotification(m_dwMonitorEvents[0]))
  102. bConinueNotifications = FALSE;
  103. if (!IsPathValid(m_strFolderPath))
  104. bConinueNotifications = FALSE;
  105. break;
  106. case WAIT_OBJECT_0 + 1:
  107. // A directory was created or deleted in C:.
  108. // Refresh the directory tree and restart the
  109. // change notification. RefreshTree is an
  110. // application-defined function.
  111. RefreshTree();
  112. if (!::FindNextChangeNotification(m_dwMonitorEvents[1]))
  113. bConinueNotifications = FALSE;
  114. if (!IsPathValid(m_strFolderPath))
  115. bConinueNotifications = FALSE;
  116. break;
  117. case WAIT_OBJECT_0 + 2:
  118. bContinueThread = TRUE;
  119. bConinueNotifications = FALSE;
  120. break;
  121. case WAIT_OBJECT_0 + 3:
  122. bContinueThread = FALSE;
  123. bConinueNotifications = FALSE;
  124. break;
  125. }
  126. }
  127. // Close the file change notification handle and return.
  128. ::FindCloseChangeNotification (m_dwMonitorEvents[0]);
  129. ::FindCloseChangeNotification (m_dwMonitorEvents[1]);
  130. m_dwMonitorEvents[0] = INVALID_HANDLE_VALUE;
  131. m_dwMonitorEvents[1] = INVALID_HANDLE_VALUE;
  132. return bContinueThread;
  133. }
  134. BOOL CXTDirWatcher::InitInstance()
  135. {
  136. BOOL bContinueThread = TRUE;
  137. while (bContinueThread)
  138. {
  139. bContinueThread = MonitorNotifications();
  140. }
  141. return FALSE;
  142. }
  143. BOOL CXTDirWatcher::IsPathValid(LPCTSTR lpszFolderPath)
  144. {
  145. if (_tcslen(lpszFolderPath) == 0)
  146. return FALSE;
  147. if (!DIRECTORYEXISTS_S(lpszFolderPath))
  148. return FALSE;
  149. return TRUE;
  150. }
  151. BOOL CXTDirWatcher::SetFolderPath(CWnd* pMainWnd, LPCTSTR lpszFolderPath)
  152. {
  153. if (IsPathValid(lpszFolderPath))
  154. {
  155. if (GetFolderData(lpszFolderPath, m_tvid))
  156. {
  157. m_pMainWnd = pMainWnd;
  158. m_strFolderPath = lpszFolderPath;
  159. SetEvent(m_dwMonitorEvents[2]);  // Folder was changed event
  160. return TRUE;
  161. }
  162. }
  163. return FALSE;
  164. }
  165. BOOL CXTDirWatcher::SetFolderData(CWnd* pMainWnd, XT_TVITEMDATA* lpTVID)
  166. {
  167. if (!lpTVID)
  168. return FALSE;
  169. TCHAR szFolderPath[_MAX_PATH];
  170. if (::SHGetPathFromIDList(lpTVID->lpifq, szFolderPath))
  171. {
  172. return SetFolderPath(pMainWnd, szFolderPath);
  173. }
  174. return FALSE;
  175. }
  176. BOOL CXTDirWatcher::GetFolderData(LPCTSTR lpszFolderPath, XT_TVITEMDATA& lpTVID)
  177. {
  178. LPITEMIDLIST  pidl;
  179. LPSHELLFOLDER pDesktopFolder;
  180. OLECHAR       szOleChar[MAX_PATH];
  181. ULONG         chEaten;
  182. ULONG         dwAttributes;
  183. if (!IsPathValid(lpszFolderPath))
  184. return FALSE;
  185. // Get a pointer to the Desktop's IShellFolder interface.
  186. if (SUCCEEDED(::SHGetDesktopFolder(&pDesktopFolder)))
  187. {
  188. // IShellFolder::ParseDisplayName requires the file name be in
  189. // Unicode.
  190. #if !defined(_UNICODE)
  191. ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpszFolderPath, -1,
  192. szOleChar, MAX_PATH);
  193. #else
  194. STRCPY_S(szOleChar, MAX_PATH, lpszFolderPath);
  195. #endif
  196. // Convert the path to an ITEMIDLIST.
  197. if (SUCCEEDED(pDesktopFolder->ParseDisplayName(NULL, NULL, szOleChar,
  198. &chEaten, &pidl, &dwAttributes)))
  199. {
  200. IShellFolder *psfMyFolder;
  201. lpTVID.lpi = lpTVID.lpifq = pidl;
  202. pDesktopFolder->BindToObject(lpTVID.lpifq, NULL,
  203. IID_IShellFolder, (LPVOID*)&psfMyFolder);
  204. lpTVID.lpsfParent = psfMyFolder;
  205. pDesktopFolder->Release();
  206. return TRUE;
  207. }
  208. pDesktopFolder->Release();
  209. }
  210. return FALSE;
  211. }
  212. void CXTDirWatcher::RefreshFolder()
  213. {
  214. m_pMainWnd->SendMessage(XTWM_SHELL_NOTIFY,
  215. SHN_XT_REFRESHFOLDER, (LPARAM)&m_tvid);
  216. }
  217. void CXTDirWatcher::RefreshTree()
  218. {
  219. m_pMainWnd->SendMessage(XTWM_SHELL_NOTIFY,
  220. SHN_XT_REFRESHTREE, (LPARAM)&m_tvid);
  221. }