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

📄 disktreectrl.cpp

📁 磁盘容量扫描、但界面和程序结构非常不错
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// DiskTreeCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "diskinfo.h"
#include "DiskTreeCtrl.h"

#include "Common/Useful.h"
#include "Common/makehtml.h"

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

int CDiskTreeCtrl::m_nSortCol = -1;
BOOL CDiskTreeCtrl::m_bSortAscending = TRUE;
int CDiskTreeCtrl::nOldProgress = -1;
long double CDiskTreeCtrl::dTotalUsedSize = 1;

/////////////////////////////////////////////////////////////////////////////
// CDiskTreeCtrl

CDiskTreeCtrl::CDiskTreeCtrl()
{
	m_nThreadCode = 1;
	m_pThread = NULL;
	m_pFolder = NULL;
}

CDiskTreeCtrl::~CDiskTreeCtrl()
{
}


BEGIN_MESSAGE_MAP(CDiskTreeCtrl, CSuperGridCtrl)
	//{{AFX_MSG_MAP(CDiskTreeCtrl)
	ON_WM_CREATE()
	ON_WM_SIZE()
	//}}AFX_MSG_MAP
	ON_NOTIFY_REFLECT(LVN_GETDISPINFO, OnGetdispinfo)
	ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnClick)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDiskTreeCtrl message handlers

void CDiskTreeCtrl::UpdateFolders()
{
	if (m_pThread || m_pFolder==NULL)
		return;

	m_nThreadCode = 1;

	DeleteAll(); 
	m_pFolder->DeleteAll();
	m_pFolder->m_bSorted = FALSE;

	CItemInfo* lpItemInfo = new CItemInfo();
	lpItemInfo->m_pFolder = m_pFolder;

	if(!CreateTreeCtrl(lpItemInfo))
		return;

	Expand(GetRootItem(), 0 /*listview index 0*/); 
	
	DISKTREETHREADPARAMS* pThreadParams = new DISKTREETHREADPARAMS;
	pThreadParams->pFolder = m_pFolder;
	pThreadParams->pTreeItem = GetRootItem();
	pThreadParams->pTreeCtrl = this;
	pThreadParams->pWnd = AfxGetMainWnd();

	m_dCurFileSize = 0;
	pThreadParams->pdFileSize = &m_dCurFileSize;
	pThreadParams->dTotalUsed = 1;
	
	CString str(m_pFolder->m_strFolderName);
	if (str.GetLength() > 3)
		pThreadParams->bIsFolder = true;
	else
	{
		DWORD dwFreeSpaceLow;
		DWORD dwFreeSpaceHigh;
		DWORD dwTotalSpaceLow;
		DWORD dwTotalSpaceHigh;
		if (GetHDSpace(str, dwFreeSpaceLow, dwFreeSpaceHigh,
			dwTotalSpaceLow, dwTotalSpaceHigh))
		{
			double dTotal = ((double)dwTotalSpaceHigh)*
				MAX_DWORD_VALUE + (double)dwTotalSpaceLow;
			double dFree = ((double)dwFreeSpaceHigh) * 
				MAX_DWORD_VALUE + (double)dwFreeSpaceLow;
			
			pThreadParams->dTotalUsed = dTotal - dFree;
		}
		
		pThreadParams->bIsFolder = false;
	}

		
	pThreadParams->pnThreadCode = &m_nThreadCode;

	//EnableWindow(FALSE);

	m_pThread = AfxBeginThread(ThreadFunc, (LPVOID)pThreadParams);
}
	
int CDiskTreeCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CSuperGridCtrl::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	if (IfNewComCtrl32())
		IE4StyleEx(LVS_EX_GRIDLINES); 

	if (m_wndFlatHeader.SubclassWindow(GetDlgItem(0)->GetSafeHwnd()) == 0)
	{
		TRACE0("Unable to subclass header control.\n");
		return -1;
	}

	//associate imagelist with listviewctrl	
	HINSTANCE hIns = AfxGetResourceHandle();
	AfxSetResourceHandle(AfxGetInstanceHandle());
	m_imgList.Create(IDB_FOLDERLIST,16,1,RGB(0, 255, 255));
	AfxSetResourceHandle(hIns);
	
	SetImageList(&m_imgList,LVSIL_SMALL);
	
	CImageList *pImageList = GetImageList(LVSIL_SMALL);
	if(pImageList)
		ImageList_GetIconSize(pImageList->m_hImageList, &m_cxImage, &m_cyImage);
	else
		return -1;

	LV_COLUMN   lvColumn;
	lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
	lvColumn.fmt = LVCFMT_CENTER;
	lvColumn.cx = 200;
	CString str;
	for(int x = 0; x < 4; x++)
    {
		str.LoadString(IDS_COL_FOLDERTREE + x);

		lvColumn.pszText = (LPTSTR)(LPCTSTR)str;
		InsertColumn(x,&lvColumn);
    }

	return 0;
}

void CDiskTreeCtrl::ResizeColumns(BOOL bInit)
{
	CRect rc;
	GetClientRect(&rc);

	int nCount = GetNumCol();
	int nWidth = 0;

	if (bInit)
	{
		nWidth = (rc.Width() - GetSystemMetrics(SM_CXHSCROLL)) / 2;

		int nSubWidth = nWidth/(nCount-1);
		int nTotalSub = 0;
		
		for (int i=1; i<nCount; i++)
		{
			nTotalSub += nSubWidth;
			SetColumnWidth(i, nSubWidth);
		}

		SetColumnWidth(0, rc.Width()- GetSystemMetrics(SM_CXHSCROLL) - nTotalSub-1);
	}
}

void CDiskTreeCtrl::DeleteAll()
{
	DeleteOneItem(FALSE);
}

UINT CDiskTreeCtrl::ThreadFunc(LPVOID pParam)
{
	DISKTREETHREADPARAMS* pThreadParams = (DISKTREETHREADPARAMS*)pParam;

	CMyFolder* pFolder = pThreadParams->pFolder;
	CDiskTreeCtrl::CTreeItem* pTreeItem = pThreadParams->pTreeItem;
	int* pnThreadCode = pThreadParams->pnThreadCode;
	CDiskTreeCtrl* pTreeCtrl = pThreadParams->pTreeCtrl;
	CWnd* pWnd = pThreadParams->pWnd;

	if (pThreadParams->bIsFolder)
		pThreadParams->dTotalUsed = GetNrSubFolders(pFolder->m_strFolderName);

	::PostMessage((HWND)pWnd->GetSafeHwnd(), WM_USER_SCANPROGRESS, SCAN_PROGRESS_SET_RANGE, MAKELPARAM(0, 20));
	::PostMessage((HWND)pWnd->GetSafeHwnd(), WM_USER_SCANPROGRESS, SCAN_PROGRESS_SET_POS, (LPARAM)0);	

	long double dFileSize = 0;
	UpdateDir(pFolder,(LPCTSTR)(pFolder->m_strFolderName), dFileSize,
		pTreeCtrl, pTreeItem, pnThreadCode, pWnd, pThreadParams, pThreadParams->bIsFolder, true);

	pFolder->SetReady(0); // Folder

	delete pThreadParams;

	if ((*pnThreadCode) == -1)
		return -1;

	pTreeCtrl->m_pThread = NULL;
	pTreeCtrl->RedrawWindow();

	if ((*pnThreadCode) == -1)
		return -1;

	if (pTreeCtrl->GetSelectedFolder() == NULL)
		pTreeCtrl->SelectNode(pTreeCtrl->GetRootItem());

	// Force view to update infos
	pTreeCtrl->GetOwner()->PostMessage(WM_FOLDER_SELECTED, 1,0); // Give int 1 to tell the scanning has just finished

	::PostMessage((HWND)pWnd->GetSafeHwnd(), WM_USER_SCANPROGRESS, SCAN_PROGRESS_FINISHED, NULL);

	return 0;
}

void CDiskTreeCtrl::UpdateDir(CMyFolder * pCurDir, const char * charPath, 
						   long double & dFileSize,
						   CDiskTreeCtrl* pTreeCtrl, 
						   CDiskTreeCtrl::CTreeItem* pTreeItem,
						   int* pnThreadCode, CWnd* pWnd,
						   DISKTREETHREADPARAMS* pThreadParams, 
						   bool bIsFolder,
						   bool bRootFolder)
{
	if ((*pnThreadCode) == -1)
		return;

	HANDLE hFind;
    WIN32_FIND_DATA fd;
    
	char charCmp[MAX_PATH];
	strcpy(charCmp, charPath);
	strcat(charCmp, "*.*");		
	long int nCurrentFileCount=0;
	double dCurFileSize=0;
	CItemInfo* lpItemInfo;

	CTreeItem* pNewItem;

    if ((hFind = ::FindFirstFile ((LPCTSTR) charCmp, &fd)) ==
        INVALID_HANDLE_VALUE) 
        return;

    do {
		if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 
		{
			strcpy(charCmp, (LPCTSTR) &fd.cFileName);
			//strlwr(charCmp); // Make lower

            if ((strcmp(charCmp, ".")!=0) && (strcmp(charCmp, "..")!=0)) 
			{
				CMyFolder* pDir = new CMyFolder();
				pDir->SetTitle(charCmp);
				pCurDir->Add(pDir);
				strcpy(charCmp, charPath);
				strcat(charCmp, (LPCTSTR) &fd.cFileName);
				strcat(charCmp, "\\");

				if ((*pnThreadCode) == -1)
					return;
				else
				{
					lpItemInfo = new CItemInfo();
					lpItemInfo->m_pFolder = pDir;

					if ((*pnThreadCode) == -1)
					{
						delete lpItemInfo;
						return;
					}else
						pNewItem = pTreeCtrl->InsertItem(pTreeItem, lpItemInfo);
				}
				
				UpdateDir(pDir, charCmp, dFileSize, pTreeCtrl, pNewItem, pnThreadCode, pWnd, 
					pThreadParams, bIsFolder);
				pDir->SetReady(0);

				if ((*pnThreadCode) == -1)
					return;
				else
				{
					int n = pTreeCtrl->GetCurIndex(pNewItem);
					if (n != -1)
						pTreeCtrl->Update(n);
				}

				if (bIsFolder && bRootFolder)
					*(pThreadParams->pdFileSize) += 1;
            }
        }else
		{
			pCurDir->m_nFileCount ++;
			pCurDir->m_dFileSize += fd.nFileSizeLow;
			dFileSize += fd.nFileSizeLow;
			dCurFileSize += fd.nFileSizeLow;
			nCurrentFileCount++;
			
			if (!bIsFolder)
				*(pThreadParams->pdFileSize) += fd.nFileSizeLow;
		}
    } while (((*pnThreadCode) != -1) && ::FindNextFile (hFind, &fd));

	::FindClose (hFind);

	//pCurDir->FreeExtra();
	if ((*pnThreadCode) != -1 && nCurrentFileCount>0) // Add File Item
	{
		CMyFolder* pDir = new CMyFolder();
		//pDir -> m_pChart = &m_wndPieChart;
		pDir->m_strFolderName.LoadString(IDS_FILES);
		pDir->m_nFileCount = nCurrentFileCount;
		pDir->m_dFileSize = dCurFileSize;
		pCurDir->Add(pDir);

		pDir->SetReady(1);

		lpItemInfo = new CItemInfo();
		lpItemInfo->m_pFolder = pDir;
		if ((*pnThreadCode) == -1)
		{
			delete lpItemInfo;
			return;
		}else
			pNewItem = pTreeCtrl->InsertItem(pTreeItem, lpItemInfo);
	}

	int i = (long int)(((*(pThreadParams->pdFileSize)) / pThreadParams->dTotalUsed)*21);
	i++; // move from 0-19 to 1-20
	if (i>20)
		i = 20;
	::PostMessage(pWnd->GetSafeHwnd(), WM_USER_SCANPROGRESS, SCAN_PROGRESS_SET_POS, (LPARAM)i);

	Sleep(0);

	/*
	int i = (int)((dFileSize / dTotalUsedSize)*110);//*135; // Fusk should be 100
	if (i>100)
		i = 100;
	if (nOldProgress != i)
	{
		// Send message to main frame to update progress bar
		nOldProgress = i;
	}*/
}

void CDiskTreeCtrl::OnGetdispinfo(NMHDR* pNMHDR, LRESULT* pResult)
{
	LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
	CTreeItem* pFileItem= (CTreeItem*) pDispInfo->item.lParam;
	LV_ITEM *pItem = &((LV_DISPINFO*)pNMHDR)->item;

	if(! (pItem->mask & LVIF_TEXT))
		return;

	CMyFolder* pFolder = pFileItem->m_lpNodeInfo->m_pFolder;

	::lstrcpy (pDispInfo->item.pszText, (LPCTSTR) pFolder->GetItemText(pDispInfo->item.iSubItem));

	*pResult = 0;
}

CString CDiskTreeCtrl::GetCurrentFolder()
{
	if (m_pFolder)
		return m_pFolder->m_strFolderName;
	else
		return CString();
	
}

int CDiskTreeCtrl::GetIcon(const CTreeItem *pItem)
{
	int iImage = 0;
	if(pItem->m_lpNodeInfo->m_pFolder->IsFile())
		iImage = 2;//doc icon
	else
		IsCollapsed(pItem) ? iImage = 1/*close icon*/:iImage = 0;/*open icon*/		

	return iImage;
}

void CDiskTreeCtrl::Stop()
{
	if (m_pThread)
	{
		m_nThreadCode = -1;
		HANDLE hThread = m_pThread->m_hThread;
		
		PumpMessages(); // Wait until send message returns.

		if (::WaitForSingleObject(hThread, 500) == WAIT_TIMEOUT)
			::TerminateThread(hThread, 0);
		//::WaitForSingleObject(hThread, INFINITE);
		m_pThread = NULL;

		::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), WM_USER_SCANPROGRESS, SCAN_PROGRESS_FINISHED, NULL);
	}
}

void CDiskTreeCtrl::Sort(CTreeItem *pParent)
{
	const int nChildren = NumChildren(pParent);
	if (nChildren > 1)
	{
		CTreeItem** ppSortArray = new CTreeItem*[nChildren];
		// Fill in array with pointers to our children.
		POSITION pos = pParent->m_listChild.GetHeadPosition();
		for (int i=0; pos; i++)
		{
			if (i < nChildren) // To be thread safe, when sorting and scanning at sametime
			{
				ppSortArray[i] = (CTreeItem*)pParent->m_listChild.GetAt(pos);
				pParent->m_listChild.GetNext(pos);
			}
		}

		qsort(ppSortArray, nChildren, sizeof(CTreeItem*), CompareChildren);
		// reorg children with new sorted list
		pos = pParent->m_listChild.GetHeadPosition();
		for (i=0; pos; i++)
		{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -