📄 ngdriveview.cpp
字号:
}
return TRUE;
}
UINT CNGDriveView::AddDirectoryNodes (HTREEITEM hItem, CString& strPathName)
{
HANDLE hFind;
WIN32_FIND_DATA fd;
UINT nCount = 0;
CString strFileSpec = strPathName;
if (strFileSpec.Right (1) != "\\")
strFileSpec += "\\";
strFileSpec += "*.*";
if ((hFind = ::FindFirstFile ((LPCTSTR) strFileSpec, &fd)) ==
INVALID_HANDLE_VALUE) {
if (IsDriveNode (hItem))
AddDummyNode (hItem);
return 0;
}
do {
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
CString strFileName = (LPCTSTR) &fd.cFileName;
if ((strFileName != ".") && (strFileName != "..")) {
HTREEITEM hChild =
GetTreeCtrl ().InsertItem ((LPCTSTR) &fd.cFileName,
ILI_CLOSED_FOLDER, ILI_OPEN_FOLDER, hItem, TVI_SORT);
CString strNewPathName = strPathName;
if (strNewPathName.Right (1) != "\\")
strNewPathName += "\\";
strNewPathName += (LPCTSTR) &fd.cFileName;
SetButtonState (hChild, strNewPathName);
nCount++;
}
}
} while (::FindNextFile (hFind, &fd));
::FindClose (hFind);
return nCount;
}
void CNGDriveView::SetButtonState (HTREEITEM hItem, CString& strPathName)
{
if (HasSubdirectory (strPathName))
AddDummyNode (hItem);
}
void CNGDriveView::UpdateButtonState (HTREEITEM hItem, CString& strPathName)
{
if (HasSubdirectory (strPathName)) {
if (!GetTreeCtrl ().ItemHasChildren (hItem)) {
AddDummyNode (hItem);
Invalidate ();
}
}
else {
if (GetTreeCtrl ().ItemHasChildren (hItem))
DeleteChildren (hItem);
}
}
BOOL CNGDriveView::HasSubdirectory (CString& strPathName)
{
HANDLE hFind;
WIN32_FIND_DATA fd;
BOOL bResult = FALSE;
CString strFileSpec = strPathName;
if (strFileSpec.Right (1) != "\\")
strFileSpec += "\\";
strFileSpec += "*.*";
if ((hFind = ::FindFirstFile ((LPCTSTR) strFileSpec, &fd)) !=
INVALID_HANDLE_VALUE) {
do {
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
CString strFileName = (LPCTSTR) &fd.cFileName;
if ((strFileName != ".") && (strFileName != ".."))
bResult = TRUE;
}
} while (::FindNextFile (hFind, &fd) && !bResult);
::FindClose (hFind);
}
return bResult;
}
BOOL CNGDriveView::IsDriveNode (HTREEITEM hItem)
{
return (GetTreeCtrl ().GetParentItem (hItem) == NULL) ? TRUE : FALSE;
}
void CNGDriveView::AddDummyNode (HTREEITEM hItem)
{
GetTreeCtrl ().InsertItem ("", 0, 0, hItem);
}
HTREEITEM CNGDriveView::FindItem (HTREEITEM hItem, CString& strTarget)
{
while (hItem != NULL) {
if (GetTreeCtrl ().GetItemText (hItem) == strTarget)
break;
hItem = GetTreeCtrl ().GetNextSiblingItem (hItem);
}
return hItem;
}
UINT CNGDriveView::DeleteChildren (HTREEITEM hItem)
{
UINT nCount = 0;
HTREEITEM hChild = GetTreeCtrl ().GetChildItem (hItem);
while (hChild != NULL) {
HTREEITEM hNextItem = GetTreeCtrl ().GetNextSiblingItem (hChild);
GetTreeCtrl ().DeleteItem (hChild);
hChild = hNextItem;
nCount++;
}
return nCount;
}
HTREEITEM CNGDriveView::GetDriveNode (HTREEITEM hItem)
{
HTREEITEM hParent;
do {
hParent = GetTreeCtrl ().GetParentItem (hItem);
if (hParent != NULL)
hItem = hParent;
} while (hParent != NULL);
return hItem;
}
DWORD CNGDriveView::GetSerialNumber (CString& strDrive)
{
DWORD dwSerialNumber;
if (!::GetVolumeInformation ((LPCTSTR) strDrive, NULL, 0,
&dwSerialNumber, NULL, NULL, NULL, 0))
dwSerialNumber = 0xFFFFFFFF;
return dwSerialNumber;
}
BOOL CNGDriveView::IsMediaValid (CString& strPathName)
{
// Return TRUE if the drive doesn't support removable media.
UINT nDriveType = GetDriveType ((LPCTSTR) strPathName);
if ((nDriveType != DRIVE_REMOVABLE) && (nDriveType != DRIVE_CDROM))
return TRUE;
// Return FALSE if the drive is empty (::GetVolumeInformation fails).
DWORD dwSerialNumber;
CString strDrive = strPathName.Left (3);
UINT nDrive = (UINT) strDrive[0] - 0x41;
if (!::GetVolumeInformation ((LPCTSTR) strDrive, NULL, 0,
&dwSerialNumber, NULL, NULL, NULL, 0)) {
m_dwMediaID[nDrive] = 0xFFFFFFFF;
return FALSE;
}
// Also return FALSE if the disk's serial number has changed.
if ((m_dwMediaID[nDrive] != dwSerialNumber) &&
(m_dwMediaID[nDrive] != 0xFFFFFFFF)) {
m_dwMediaID[nDrive] = dwSerialNumber;
return FALSE;
}
// Update our record of the serial number and return TRUE.
m_dwMediaID[nDrive] = dwSerialNumber;
return TRUE;
}
BOOL CNGDriveView::IsPathValid (CString& strPathName)
{
if (strPathName.GetLength () == 3)
return TRUE;
WIN32_FIND_DATA fd;
BOOL bResult = FALSE;
HANDLE hFind = ::FindFirstFile ((LPCTSTR) strPathName, &fd);
if (INVALID_HANDLE_VALUE != hFind)
{
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
bResult = TRUE;
// Close the handle
// This may cause a first chance exception
// Hence the SEH handler around it....
__try
{
::CloseHandle (hFind);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DWORD dwCode = GetExceptionCode();
TRACE1("\tException Code: 0x%X\n", dwCode);
}
}
return bResult;
}
void CNGDriveView::RefreshDirectory (HTREEITEM hItem)
{
// If the item is not expanded, update its button state and return.
if (!(GetTreeCtrl ().GetItemState (hItem, TVIS_EXPANDED) &
TVIS_EXPANDED) || !GetTreeCtrl ().ItemHasChildren (hItem)) {
if (!IsDriveNode (hItem)) {
CString strPathName = GetPathFromItem (hItem);
UpdateButtonState (hItem, strPathName);
GetTreeCtrl ().Expand (hItem, TVE_COLLAPSE);
}
return;
}
// Delete items corresponding to subdirectories that no longer exist
// and build a CStringList containing the names of all the items that
// are children of hItem.
CStringList list;
WIN32_FIND_DATA fd;
HANDLE hFind;
HTREEITEM hChild = GetTreeCtrl ().GetChildItem (hItem);
while (hChild != NULL) {
HTREEITEM hNextItem = GetTreeCtrl ().GetNextSiblingItem (hChild);
CString strDirName = GetTreeCtrl ().GetItemText (hChild);
if ((hFind = ::FindFirstFile ((LPCTSTR) strDirName, &fd)) !=
INVALID_HANDLE_VALUE) {
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
list.AddTail (strDirName);
else
GetTreeCtrl ().DeleteItem (hChild);
::FindClose (hFind);
}
else
GetTreeCtrl ().DeleteItem (hChild);
hChild = hNextItem;
}
// Add items for newly created subdirectories.
if ((hFind = ::FindFirstFile ("*.*", &fd)) != INVALID_HANDLE_VALUE) {
do {
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
CString strFileName = (LPCTSTR) &fd.cFileName;
if ((strFileName != ".") && (strFileName != "..")) {
if (list.Find (strFileName) == NULL) {
hChild = GetTreeCtrl ().InsertItem (strFileName,
ILI_CLOSED_FOLDER, ILI_OPEN_FOLDER,
hItem, TVI_SORT);
CString strPathName = GetPathFromItem (hChild);
SetButtonState (hChild, strPathName);
list.AddTail (strFileName);
}
}
}
} while (::FindNextFile (hFind, &fd));
::FindClose (hFind);
}
// Remove all items from the CStringList.
list.RemoveAll ();
// Now repeat this procedure for hItem's children.
hChild = GetTreeCtrl ().GetChildItem (hItem);
while (hChild != NULL) {
CString string = GetTreeCtrl ().GetItemText (hChild);
::SetCurrentDirectory ((LPCTSTR) string);
RefreshDirectory (hChild); // Recursion!
::SetCurrentDirectory ("..");
hChild = GetTreeCtrl ().GetNextSiblingItem (hChild);
}
}
void CNGDriveView::CreateMonitoringThread (CString& strDrive)
{
PTHREADINFO pThreadInfo = new THREADINFO; // Thread will delete
pThreadInfo->nDrive = (UINT) strDrive[0] - 0x41;
pThreadInfo->hEvent = m_event.m_hObject;
pThreadInfo->hWnd = m_hWnd;
CWinThread* pThread = AfxBeginThread (ThreadFunc, pThreadInfo,
THREAD_PRIORITY_IDLE);
m_hThreads[m_nThreadCount++] = pThread->m_hThread;
}
/////////////////////////////////////////////////////////////////////////
// Thread function for detecting file system changes
UINT CNGDriveView::ThreadFunc (LPVOID pParam)
{
PTHREADINFO pThreadInfo = (PTHREADINFO) pParam;
UINT nDrive = pThreadInfo->nDrive;
HANDLE hEvent = pThreadInfo->hEvent;
HWND hWnd = pThreadInfo->hWnd;
delete pThreadInfo;
CString strDrive = "?:\\";
strDrive.SetAt (0, (TCHAR)(0x41 + nDrive));
// Get a handle to a file change notification object.
HANDLE hChange = ::FindFirstChangeNotification ((LPCTSTR) strDrive,
TRUE, FILE_NOTIFY_CHANGE_DIR_NAME);
// Return now if ::FindFirstChangeNotification failed.
if (hChange == INVALID_HANDLE_VALUE)
return 1;
HANDLE aHandles[2];
aHandles[0] = hChange;
aHandles[1] = hEvent;
BOOL bContinue = TRUE;
// Sleep until a file change notification wakes this thread or
// m_event becomes set indicating it's time for the thread to end.
while (bContinue) {
if (::WaitForMultipleObjects (2, aHandles, FALSE, INFINITE) -
WAIT_OBJECT_0 == 0) { // Respond to a change notification.
::PostMessage (hWnd, WM_USER, (WPARAM) nDrive, 0);
::FindNextChangeNotification (hChange);
}
else // Kill this thread (m_event became signaled).
bContinue = FALSE;
}
// Close the file change notification handle and return.
::FindCloseChangeNotification (hChange);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -