⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ngdriveview.cpp

📁 ResOrg 图形化管理Vc项目的资源ID的工具的源代码。 ResOrg - Manage and Renumber Resource Symbol IDs Introduction The
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    }

    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 + -