/**************************************************************************
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;
}