Click here to Skip to main content
15,881,704 members
Articles / Desktop Programming / MFC

System Drives Browsing Tree

Rate me:
Please Sign up or sign in to vote.
3.36/5 (11 votes)
3 Aug 2002 73.5K   1.1K   11  
System Drives Browsing Tree
/**************************************************************************
   THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF
   ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
   THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
   PARTICULAR PURPOSE.
   Author: Barretto VN  7/2001
**************************************************************************/

/****************************************************
	The followinf Member Functions were copied from
	an article by Jeff Prosise available on the
	MSDN CD.

  1) AddDrives
  2) AddDirectoryNodes
  3) AddDumyNodes
  4) DeleteChildren
  5) GetDriveNode
  6) GetPathFromItem
  7) HasSubDirectory
  8) InitTree
  9) IsDriveNode
 10) IsMediaValid
 11) SetButtonState

*****************************************************/

// DriveBrowser.cpp : implementation file
//

#include "stdafx.h"
#include "DriveBrowsingTree.h"
#include "DriveBrowser.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define ILI_CDDRV     0
#define ILI_CLSDFLD   1
#define ILI_DRIVE     2 
#define ILI_FLOPPYDRV 3 
#define ILI_MYCOMP    4
#define ILI_OPENFLD   5 
#define ILI_TEXTFILE  6 

#define MYCOMPUTER "My Computer"
/////////////////////////////////////////////////////////////////////////////
// CDriveBrowser

IMPLEMENT_DYNCREATE(CDriveBrowser, CTreeView)

CDriveBrowser::CDriveBrowser()
{
}

CDriveBrowser::~CDriveBrowser()
{
}


BEGIN_MESSAGE_MAP(CDriveBrowser, CTreeView)
	//{{AFX_MSG_MAP(CDriveBrowser)
	ON_WM_DESTROY()
	ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnItemexpanding)
	ON_NOTIFY_REFLECT(TVN_SELCHANGING, OnSelchanging)
	ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclk)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDriveBrowser drawing

void CDriveBrowser::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
	// TODO: add draw code here
}

/////////////////////////////////////////////////////////////////////////////
// CDriveBrowser diagnostics

#ifdef _DEBUG
void CDriveBrowser::AssertValid() const
{
	CTreeView::AssertValid();
}

void CDriveBrowser::Dump(CDumpContext& dc) const
{
	CTreeView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CDriveBrowser message handlers

BOOL CDriveBrowser::PreCreateWindow(CREATESTRUCT& cs) 
{
	// TODO: Add your specialized code here and/or call the base class
	cs.style |= TVS_HASBUTTONS | TVS_LINESATROOT | TVS_HASLINES;	
	return CTreeView::PreCreateWindow(cs);
}


void CDriveBrowser::OnInitialUpdate() 
{
	CTreeView::OnInitialUpdate();
	
	// TODO: Add your specialized code here and/or call the base class

	CWinApp* pApp = AfxGetApp();

	//	ASSERT(m_pImageList != NULL);    // serious allocation failure checking
	m_pImageList.Create(16, 16, ILC_COLOR8 | ILC_MASK,  9, 9);

	m_pImageList.Add(pApp->LoadIcon(ICO_CDDRV));
	m_pImageList.Add(pApp->LoadIcon(ICO_CLSDFLD));
	m_pImageList.Add(pApp->LoadIcon(ICO_DRIVE));
	m_pImageList.Add(pApp->LoadIcon(ICO_FLOPPYDRV));
	m_pImageList.Add(pApp->LoadIcon(ICO_MYCOMP));
	m_pImageList.Add(pApp->LoadIcon(ICO_OPENFLD));
	m_pImageList.Add(pApp->LoadIcon(ICO_TEXTFILE));


	GetTreeCtrl().SetImageList(&m_pImageList , TVSIL_NORMAL);

	HTREEITEM hParent = GetTreeCtrl().InsertItem(MYCOMPUTER, ILI_MYCOMP, ILI_MYCOMP);
	InitTreeView(hParent);
	GetTreeCtrl().Expand(hParent, TVE_EXPAND); 

}

void CDriveBrowser::InitTreeView(HTREEITEM hParent)
{

	int nPos = 0;
    UINT nCount = 0;
    CString strDrive = "?:\\";

    DWORD dwDriveList = ::GetLogicalDrives ();

	CString cTmp;
	
    while (dwDriveList) {
        if (dwDriveList & 1) {
			cTmp = strDrive;
            strDrive.SetAt (0, 0x41 + nPos);
            if (AddDrives(strDrive , hParent))
                nCount++;
        }
        dwDriveList >>= 1;
        nPos++;
    }
    return;
}


BOOL CDriveBrowser::AddDrives(CString strDrive, HTREEITEM hParent)
{

	HTREEITEM hItem;
    UINT nType = ::GetDriveType ((LPCTSTR) strDrive);
    UINT nDrive = (UINT) strDrive[0] - 0x41;

    switch (nType) {

    case DRIVE_REMOVABLE:
		hItem = GetTreeCtrl().InsertItem(strDrive, ILI_FLOPPYDRV, ILI_FLOPPYDRV, hParent);
		AddDummyNode(hItem);
        break;

    case DRIVE_FIXED:
		hItem = GetTreeCtrl().InsertItem(strDrive,  ILI_DRIVE, ILI_DRIVE, hParent);
		AddDummyNode(hItem);
        break;

    case DRIVE_REMOTE:
        hItem = GetTreeCtrl().InsertItem(strDrive, ILI_DRIVE, ILI_DRIVE, hParent);
		AddDummyNode(hItem);
        break;

    case DRIVE_CDROM:
        hItem = GetTreeCtrl().InsertItem(strDrive, ILI_CDDRV, ILI_CDDRV, hParent);
		AddDummyNode(hItem);
        break;

    case DRIVE_RAMDISK:
        hItem = GetTreeCtrl().InsertItem(strDrive, ILI_CDDRV, ILI_CDDRV, hParent);
		AddDummyNode(hItem);
        break;

    default:
        return FALSE;
    }

	return true;

}

void CDriveBrowser::OnDestroy() 
{
	CTreeView::OnDestroy();
	
	// TODO: Add your message handler code here

	if(m_pImageList != NULL)
		m_pImageList.DeleteImageList();

}

void CDriveBrowser::AddDummyNode(HTREEITEM hItem)
{
	GetTreeCtrl().InsertItem ("", 0, 0, hItem);
}

CString CDriveBrowser::GetPathFromItem(HTREEITEM hItem)
{


    CString strPathName;
    while (hItem != NULL) 
	{
		CString string = GetTreeCtrl().GetItemText (hItem);
        if ((string.Right (1) != "\\") && !strPathName.IsEmpty ())
	        string += "\\";
		strPathName = string + strPathName;
        hItem = GetTreeCtrl().GetParentItem (hItem);
    }
	
	if(strPathName.Left(11) == MYCOMPUTER && strPathName.GetLength() > 11)
		strPathName = strPathName.Mid(12);

	return strPathName;

}

BOOL CDriveBrowser::IsPathValid(CString &strPathName)
{

    if (strPathName.GetLength() == 3)
        return TRUE;

    HANDLE hFind;
    WIN32_FIND_DATA fd;
    BOOL bResult = FALSE;

    if ((hFind = ::FindFirstFile ((LPCTSTR) strPathName, &fd)) != INVALID_HANDLE_VALUE) 
	{
        if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            bResult = TRUE;

        ::FindClose(hFind);
    }
    return bResult;
}

BOOL CDriveBrowser::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;
}



HTREEITEM CDriveBrowser::GetDriveNode(HTREEITEM hItem)
{

    HTREEITEM hParent;

    do {
        hParent = GetTreeCtrl().GetParentItem (hItem);
        if (hParent != NULL)
            hItem = hParent;
    } while (hParent != NULL);
    return hItem;

}

UINT CDriveBrowser::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++;

//		dwTreeItemCount--;

    }
    return nCount;

}

UINT CDriveBrowser::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;
    }

	CWaitCursor wait;
//	m_LocalFiles.DeleteAllItems();

    do {
        if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 
		{
            CString strFileName = (LPCTSTR) &fd.cFileName;
            if ((strFileName != ".") && (strFileName != "..")
				 && (fd.dwFileAttributes != 22))
			{
                HTREEITEM hChild =
                    GetTreeCtrl().InsertItem ((LPCTSTR) &fd.cFileName,
					ILI_CLSDFLD , ILI_OPENFLD , hItem , TVI_SORT);

                CString strNewPathName = strPathName;
                if (strNewPathName.Right (1) != "\\")
                    strNewPathName += "\\";

                strNewPathName += (LPCTSTR) &fd.cFileName;
                SetButtonState (hChild, strNewPathName);
                nCount++;
	        }
		}
		else
		{
           CString strFileName = (LPCTSTR) &fd.cFileName;

           HTREEITEM hChild =
                    GetTreeCtrl().InsertItem ((LPCTSTR) &fd.cFileName,
					ILI_TEXTFILE , ILI_TEXTFILE , hItem , TVI_SORT);
			
		}	

    } while (::FindNextFile (hFind, &fd));

    ::FindClose (hFind);

    return nCount;

}

void CDriveBrowser::SetButtonState(HTREEITEM hItem, CString &strPathName)
{
    if (HasSubdirectory (strPathName))
        AddDummyNode (hItem);
}

BOOL CDriveBrowser::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 CDriveBrowser::IsDriveNode(HTREEITEM hItem)
{

    return (GetTreeCtrl().GetParentItem (hItem) == NULL) ? TRUE : FALSE;
}

void CDriveBrowser::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here
    HTREEITEM hItem = pNMTreeView->itemNew.hItem;
    CString strPathName = GetPathFromItem (hItem);

    if (!IsMediaValid (strPathName)) 
	{
        HTREEITEM hRoot = GetDriveNode (hItem);
        GetTreeCtrl().Expand (hRoot, TVE_COLLAPSE);
        DeleteChildren (hRoot);
        AddDummyNode (hRoot);
        *pResult = TRUE;
        return;
    }


    // Delete the item if strPathName no longer specifies a valid path.
    if (!IsPathValid (strPathName)) 
	{
        if(strPathName != MYCOMPUTER && strPathName != "")
		{
			GetTreeCtrl().DeleteItem (hItem);
	        *pResult = TRUE;
		    return;
		}
    }

	CWaitCursor wait;
    // If the item is expanding, delete the dummy item attached to it
    // and add folder items. If the item is collapsing instead, delete
    // its folder items and add a dummy item if appropriate.
    if (pNMTreeView->action == TVE_EXPAND) 
	{
		if(strPathName != MYCOMPUTER)
		{
			DeleteChildren (hItem);
	        if (!AddDirectoryNodes (hItem, strPathName))
		        *pResult = TRUE;
		}
    }
    else {
		if(strPathName != MYCOMPUTER)
		{
			DeleteChildren (hItem);
	        if (IsDriveNode (hItem))
		        AddDummyNode (hItem);
			else
				SetButtonState (hItem, strPathName);
		}
    }	
		
	m_LocalPath = strPathName;

	*pResult = 0;
}


void CDriveBrowser::OnSelchanging(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here

    HTREEITEM hItem = pNMTreeView->itemNew.hItem;

    CString strPathName = GetPathFromItem (hItem);
	*pResult = FALSE;

	if(strPathName == MYCOMPUTER)
		return;

 	CWaitCursor wait;

    if (!AddDirectoryNodes (hItem, strPathName))
       *pResult = TRUE;


	m_LocalPath = strPathName;
	*pResult = 0;
}

void CDriveBrowser::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here

	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here

    HTREEITEM hItem = pNMTreeView->itemNew.hItem;
    CString strPathName = GetPathFromItem (hItem);

//	strPathName =  strPathName + GetTreeCtrl().GetItemText(hItem);	
	//ShellExecute(this->m_hWnd, "open", lvi.pszText, NULL, NULL, SW_SHOWNORMAL);
	
	*pResult = 0;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.


Written By
India India
Nothing to boast about

Comments and Discussions