📄 disktreectrl.cpp
字号:
// 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 + -