www.pudn.com > DiskInfo.tgz > DiskListCtrl.cpp
// DiskListCtrl.cpp : implementation file
// BY Yuheng Zhao 1999-1
//
// To optimize
// Improve HitTestEx(..)
// Save ClientRect
#include "stdafx.h"
#include "diskinfo.h"
#include "DiskListCtrl.h"
#include "Common/Useful.h"
#include "Common/memDC.h"
#include "Common/DrawEx.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
int CDiskListCtrl::m_nSortCode;
/////////////////////////////////////////////////////////////////////////////
// CDiskListCtrl
CDiskListCtrl::CDiskListCtrl()
{
m_nMouseInCode = 1000; //0-n buttons -1 - -6 title bar
m_nMouseDownCode = 1000;
m_bMouseDown = FALSE;
m_nSortCode = -100;
m_nNrThread = 0;
}
CDiskListCtrl::~CDiskListCtrl()
{
DeleteAll();
}
BEGIN_MESSAGE_MAP(CDiskListCtrl, CWnd)
//{{AFX_MSG_MAP(CDiskListCtrl)
ON_WM_PAINT()
ON_WM_ERASEBKGND()
ON_WM_SETCURSOR()
ON_WM_CREATE()
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_TIMER()
//}}AFX_MSG_MAP
ON_MESSAGE(WM_DISKLIST_UPDATE, OnItemUpdate)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDiskListCtrl message handlers
BOOL CDiskListCtrl::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
// TODO: Add your specialized code here and/or call the base class
static CString className = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW);
return CWnd::CreateEx(NULL, ///*WS_EX_CLIENTEDGE WS_EX_STATICEDGE,
className, NULL, dwStyle,
rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,
pParentWnd->GetSafeHwnd(), (HMENU) nID);
}
CDiskListCtrl::CItemInfo::CItemInfo(CDiskListCtrl* pCtrl)
{
m_pCtrl = pCtrl;
Reset();
}
CDiskListCtrl::CItemInfo::~CItemInfo()
{
StopThread();
}
BOOL CDiskListCtrl::CItemInfo::Update()
{
BOOL bChanged = FALSE;
m_nDriveType = ::GetDriveType((LPCTSTR)m_strDriveName);
CString strTemp;
char driveName[32];
char driveType[32];
DWORD dwDword1, dwDword2, dwDword3;
if (::GetVolumeInformation(
m_strDriveName,
driveName, 32, &dwDword1, &dwDword2, &dwDword3,
driveType, 32))
{
if (!m_bAvailable)
{
m_bAvailable = TRUE;
bChanged = TRUE;
}
strTemp = driveName;
strTemp.MakeLower();
strTemp = strTemp.Right(strTemp.GetLength()-1);
strTemp = CString(driveName).Left(1) + strTemp;
strTemp += " (" + m_strDriveName.Left(m_strDriveName.GetLength()-1) + ")";
if (strTemp != m_strTitle)
{
m_strTitle = strTemp;
bChanged = TRUE;
}
//Type
strTemp = driveType;
if (strTemp.CompareNoCase(_T("FAT")) == 0)
strTemp = _T("FAT16");
if (strTemp != m_strPartitionType)
{
m_strPartitionType = strTemp;
bChanged = TRUE;
}
}else
{
if (m_nDriveType == DRIVE_REMOVABLE || m_nDriveType ==
DRIVE_REMOTE || m_nDriveType == DRIVE_CDROM)
{
if (m_bAvailable != FALSE)
{
m_bAvailable = FALSE;
bChanged = TRUE;
}
}else
{
/*
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL,
SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf, 0, NULL );// Process any inserts in lpMsgBuf.
CString strError(m_strDriveName + "..." + CString((LPCSTR)lpMsgBuf));
CFunctionLog log(strError, 5);
//MessageBox( NULL, lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
/// Free the buffer.
LocalFree( lpMsgBuf );*/
}
}
if (m_bAvailable)
{
// Spaces
DWORD dwFreeSpaceLow;
DWORD dwFreeSpaceHigh;
DWORD dwTotalSpaceLow;
DWORD dwTotalSpaceHigh;
if (GetHDSpace(m_strDriveName, dwFreeSpaceLow, dwFreeSpaceHigh,
dwTotalSpaceLow, dwTotalSpaceHigh))
{
long double ldTotal = ((long double)dwTotalSpaceHigh)*
MAX_DWORD_VALUE + (long double)dwTotalSpaceLow;
long double ldFree = ((long double)dwFreeSpaceHigh) *
MAX_DWORD_VALUE + (long double)dwFreeSpaceLow;
// Total
if (ldTotal != m_ldTotalSpace)
{
m_ldTotalSpace = ldTotal;
bChanged = TRUE;
}
// Free
if (ldFree != m_ldFreeSpace)
{
m_ldFreeSpace = ldFree;
bChanged = TRUE;
}
}
}
return bChanged;
}
BOOL CDiskListCtrl::AddDrive(const CString &str)
{
CItemInfo* pItem = new CItemInfo(this);
pItem->m_strDriveName = str;
try
{
m_arrayDrive.Add(pItem);
return TRUE;
}
catch (CMemoryException* e)
{
CString strTemp, strMes;
strTemp.LoadString(IDS_ERR_OUTOFMEM);
strMes.Format(strTemp, 2012);
AfxMessageBox(strMes);
if (pItem !=NULL)
delete pItem;
e->Delete();
return FALSE;
}
return TRUE;
}
BOOL CDiskListCtrl::AddFolder(const CString &str)
{
CItemInfo* pItem = new CItemInfo(this);
pItem->m_strDriveName = str;
if (str.Right(1)!="\\")
pItem->m_strDriveName += "\\";
try
{
m_arrayFolder.Add(pItem);
return TRUE;
}
catch (CMemoryException* e)
{
CString strTemp, strMes;
strTemp.LoadString(IDS_ERR_OUTOFMEM);
strMes.Format(strTemp, 2012);
AfxMessageBox(strMes);
if (pItem !=NULL)
delete pItem;
e->Delete();
return FALSE;
}
return TRUE;
}
void CDiskListCtrl::CItemInfo::Reset()
{
m_bAvailable = FALSE;
m_nDriveType = -1;
m_strDriveName = _T("");
m_strTitle = _T("");
m_strPartitionType = _T("");
m_nFileCount = -1;
m_nFolderCount = 0;
m_ldTotalSpace = 0; // Numbers of files in folder mode
m_ldFreeSpace = 0; // Numbers of folders in folder mode
m_pThread = NULL;
m_nThreadCode = 1;
}
void CDiskListCtrl::DeleteAll()
{
int nCount = m_arrayDrive.GetSize();
for (int i = 0; i < nCount; i++)
delete m_arrayDrive.GetAt(i);
m_arrayDrive.RemoveAll();
EmptyFolderArray();
}
void CDiskListCtrl::OnPaint()
{
CPaintDC dc(this); // device context for painting
CRect rcClient;
GetClientRect(&rcClient);
CRect rcItem;
COLORREF colorFace = GetSysColor(COLOR_BTNFACE);
COLORREF colorShadow = GetSysColor(COLOR_3DSHADOW);
COLORREF colorLight = GetSysColor(COLOR_3DHILIGHT);
CMemDC dcMem(&dc);
BOOL bUseBmp = FALSE;
if (m_bEnableBackground)
{
// Check system color >16 bit
bUseBmp = TRUE; //Update later
}
CFont* pFont = CFont::FromHandle((HFONT)GetStockObject(DEFAULT_GUI_FONT));
CString strText;
//CFont* pOldFont = dcMem.SelectObject(&m_fontTitle);
CFont* pOldFont = dcMem.SelectObject(pFont);
COLORREF oldTextColor = dcMem.SetTextColor(RGB(0,0,0));
int oldBkMod = dcMem.SetBkMode(TRANSPARENT);
int nDriveSize = GetDriveSize();
int nFolderSize = GetFolderSize();
if (nDriveSize != 0)
{
// Title
GetItemRect(rcClient, rcItem, -1, -1);
dcMem.FillSolidRect(rcItem, colorFace);
// Paint title Text
for (int i=1; i<7;i++)
{
GetItemRect(rcClient, rcItem, -1, i);
switch (i)
{
case 1:
strText.LoadString(IDS_TITLE);
//rectText.left -= 20;
break;
case 2:
strText.LoadString(IDS_TYPE);
break;
case 3:
strText.LoadString(IDS_TOTAL);
break;
case 4:
strText.LoadString(IDS_USAGE);
break;
case 5:
strText.LoadString(IDS_USED);
break;
case 6:
strText.LoadString(IDS_FREE);
break;
}
if (i == -m_nMouseInCode && (m_nMouseDownCode>=1000 || m_nMouseDownCode == m_nMouseInCode))
dcMem.SetTextColor(RGB(0,0,128));
dcMem.DrawText(strText, rcItem, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
if (i == -m_nMouseInCode && (m_nMouseDownCode>=1000 || m_nMouseDownCode == m_nMouseInCode))
{
dcMem.SetTextColor(RGB(0,0,0));
if (m_bMouseDown)
dcMem.Draw3dRect(rcItem, colorShadow, colorLight);
else
dcMem.Draw3dRect(rcItem, colorLight, colorShadow);
}
}
}
// Drive Buttons
GetItemRect(rcClient, rcItem, -2, -1);
if (bUseBmp && !m_bmpDriveBack.IsEmpty())
m_bmpDriveBack.FillDIB(&dcMem, rcItem);
else
dcMem.FillSolidRect(rcItem, colorLight);
GetItemRect(rcClient, rcItem, -2, 6);
if (bUseBmp && !m_bmpFreeBack.IsEmpty())
m_bmpFreeBack.FillDIB(&dcMem, rcItem);
else
dcMem.FillSolidRect(rcItem, colorFace);
//GetItemRect(rcClient, rcItem, -3, 6);
//dcMem.FillSolidRect(rcItem, colorFace);
// Folder buttons
GetItemRect(rcClient, rcItem, -4, -1);
if (bUseBmp && !m_bmpFolderBack.IsEmpty())
m_bmpFolderBack.FillDIB(&dcMem, rcItem);
else
dcMem.FillSolidRect(rcItem, colorLight);
// High light
if (m_nMouseInCode>=0 && m_nMouseInCode<1000 &&
(m_nMouseDownCode>=1000 || m_nMouseDownCode == m_nMouseInCode))
{
GetItemRect(rcClient, rcItem, m_nMouseInCode, -1);
if (m_bMouseDown)
{
if (bUseBmp && !m_bmpPressedBack.IsEmpty())
m_bmpPressedBack.FillDIB(&dcMem, rcItem);
else
dcMem.FillSolidRect(rcItem, colorFace);
dcMem.Draw3dRect(rcItem, colorShadow, colorLight);
}else
{
if (bUseBmp && !m_bmpHighBack.IsEmpty())
m_bmpHighBack.FillDIB(&dcMem, rcItem);
else
dcMem.FillSolidRect(rcItem, colorFace);
dcMem.Draw3dRect(rcItem, colorLight, colorShadow);
}
}
// Border
GetItemRect(rcClient, rcItem, -5, -1);
dcMem.Draw3dRect(rcItem, colorShadow, colorLight);
// Total info Button
if (nDriveSize != 0)
{
GetItemRect(rcClient, rcItem, -3, -1);
rcItem.InflateRect(1,0);
if (nFolderSize == 0)
rcItem.bottom ++;
if (bUseBmp && !m_bmpTotalBack.IsEmpty())
m_bmpTotalBack.FillDIB(&dcMem, rcItem);
else
dcMem.FillSolidRect(rcItem, colorFace);
rcItem.DeflateRect(2,0);
if (nFolderSize != 0)
dcMem.DrawEdge(rcItem, BDR_RAISEDINNER, BF_BOTTOM|BF_TOP);
else
dcMem.DrawEdge(rcItem, BDR_RAISEDINNER, BF_TOP);
}
for (int i = 0; i < nDriveSize; i++)
DrawDrive(&dcMem, rcClient, i);
for (i = 0; i < nFolderSize; i++)
DrawFolder(&dcMem, rcClient, i);
//pFont = CFont::FromHandle((HFONT)GetStockObject(SYSTEM_FONT));
//dcMem.SelectObject(pFont);
dcMem.SetTextColor(RGB(0,0,128));
if (nDriveSize != 0)
DrawTotalItem(&dcMem, rcClient);
dcMem.SelectObject(pOldFont);
dcMem.SetTextColor(oldTextColor);
dcMem.SetBkMode(oldBkMod);
}
BOOL CDiskListCtrl::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
void CDiskListCtrl::GetItemRect(const CRect &rcClient,
CRect &rc, int nType, int nPos)
{
// nType -1 = titlebar
// nType -2 = All Drivebuttons
// nType -3 = total info button
// nType -4 = All folderbuttons
// nType -5 = Border rect
// nType 0- = for button number
CRect rcC(rcClient);
rcC.DeflateRect(1,1,1,1);
rc = rcC;
int nDriveSize = GetDriveSize();
int nHeight = GetItemHeight(rcClient);
int nTitleHeight = GetItemHeight(rcClient, TRUE);
switch (nType)
{
case -1:
rc.top = 0;
rc.bottom = nTitleHeight;
rc.left -= 1;
rc.right += 1;
break;
case -2:
rc.top = nTitleHeight + 1; // Plus border
rc.bottom = rc.top + nHeight*nDriveSize;
break;
case -3:
rc.top = nTitleHeight + 1 + nHeight*nDriveSize; // Plus border
rc.bottom = rc.top + nHeight;
rc.left -= 1;
rc.right += 1;
break;
case -4:
rc.top = nTitleHeight + 1 + nHeight*(nDriveSize+(nDriveSize!=0)); // Plus border
rc.bottom = rc.top + nHeight*GetFolderSize();
break;
case -5:
rc.top = nTitleHeight;
rc.bottom = rcC.bottom+1;
rc.left -= 1;
rc.right += 1;
break;
default:
if (nType>=100) // Folders
rc.top = nTitleHeight + 1 + nHeight*((nType-100)+(nDriveSize!=0)+nDriveSize);
else
rc.top = nTitleHeight + 1 + nHeight*nType;
rc.bottom = rc.top + nHeight;
}
if (nPos == -1)
return;
// nPos -1 = Max Width
// nPos 0-n = for every column
// nPos in percent
// 4 20 11 15 15,6 15,6 18,8
// 0 <= nCode <= 6
// Drive item rects
if (nType<100)
{
double dWidth[7] = {0.04, 0.242, 0.11, 0.156, 0.14, 0.156, 0.156};
double dOff = 0;
int nTotal = rcC.Width();
for (int i=0; i -1; i--)
{
if (!m_arrayItem.GetAt(i)->m_bIsDrive)
nCount --;
}
return nCount;*/
}
int CDiskListCtrl::GetFolderSize()
{
return m_arrayFolder.GetSize();
/*
for (int i = nCount-1; i > -1; i--)
{
if (m_arrayItem.GetAt(i)->m_bIsDrive)
nCount --;
}
return nCount;*/
}
BOOL CDiskListCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
SetCursor(LoadCursor(NULL, IDC_ARROW));
return TRUE;
}
void CDiskListCtrl::DrawTotalItem(CDC *pDC, const CRect& rcClient)
{
int nCount;
long double ldTotal, ldFree;
GetTotalUsage(nCount, ldTotal, ldFree);
CRect rcItem;
// Draw Total info
GetItemRect(rcClient, rcItem, -3, 1);
CString str, str1;
str1.LoadString(IDS_TOTAL_DRIVES);
str.Format(str1, nCount);
pDC->DrawText(str, rcItem, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
GetItemRect(rcClient, rcItem, -3, 3);
FormatByteSize(ldTotal, str);
pDC->DrawText(str, rcItem, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
long double ldUsed = ldTotal - ldFree;
GetItemRect(rcClient, rcItem, -3, 4);
rcItem.DeflateRect(0, 2);
str.Format("%.0f%%", (ldTotal==0)?0:(ldUsed/ldTotal)*100);
DrawPercentBar(pDC, rcItem, (ldTotal==0)?0:ldUsed/ldTotal,
str, GetFont());
GetItemRect(rcClient, rcItem, -3, 5);
FormatByteSize(ldUsed, str);
pDC->DrawText(str, rcItem, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
GetItemRect(rcClient, rcItem, -3, 6);
FormatByteSize(ldFree, str);
pDC->DrawText(str, rcItem, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
}
void CDiskListCtrl::DrawFolder(CDC *pDC, const CRect& rcClient, int nItem)
{
CRect rcItem;
CItemInfo* pItem = m_arrayFolder.GetAt(nItem);
CString str, strTemp;
// Image
GetItemRect(rcClient, rcItem, nItem+100, 0);
rcItem.left += (rcItem.Width() - 16) / 2;
rcItem.top += (rcItem.Height() - 16) / 2;
if (pItem->m_pThread)
m_imgTypeList.Draw(pDC, 7, rcItem.TopLeft(), ILD_NORMAL);
else
m_imgTypeList.Draw(pDC, 6, rcItem.TopLeft(), ILD_NORMAL);
GetItemRect(rcClient, rcItem, nItem+100, 1);
rcItem.left += 2;
rcItem.right -= 2;
::DrawTextEx (pDC->m_hDC,
pItem->m_strDriveName.GetBuffer (0),
pItem->m_strDriveName.GetLength(),
&rcItem,
DT_SINGLELINE | DT_VCENTER | DT_LEFT | DT_PATH_ELLIPSIS,
NULL);
if (pItem->GetFinished())
{
GetItemRect(rcClient, rcItem, nItem+100, 2);
rcItem.left += 2;
strTemp.LoadString(IDS_COUNT_FOLDER);
str.Format(strTemp, pItem->m_nFolderCount);
pDC->DrawText(str, rcItem, DT_SINGLELINE | DT_VCENTER | DT_LEFT);
GetItemRect(rcClient, rcItem, nItem+100, 3);
rcItem.left += 2;
strTemp.LoadString(IDS_COUNT_FILE);
str.Format(strTemp, pItem->m_nFileCount);
pDC->DrawText(str, rcItem, DT_SINGLELINE | DT_VCENTER | DT_LEFT);
GetItemRect(rcClient, rcItem, nItem+100, 4);
rcItem.left += 2;
FormatByteSize(pItem->m_ldTotalSpace, str);
pDC->DrawText(str, rcItem, DT_SINGLELINE | DT_VCENTER | DT_LEFT);
}else
{
GetItemRect(rcClient, rcItem, nItem+100, 2);
rcItem.left += 2;
str.LoadString(IDS_ABORTED);
pDC->DrawText(str, rcItem, DT_SINGLELINE | DT_VCENTER | DT_LEFT);
}
// Alert indicator
GetItemRect(rcClient, rcItem, nItem+100, 5);
rcItem.left += 2;
rcItem.top += (rcItem.Height() - 16) / 2;
double dMb = pItem->m_ldTotalSpace / (1024*1024);
int nMode = ( dMb> m_dRedAlert)? 2 :
((dMb > m_dYellowAlert)? 1 : 0);
for (int i=0; i<3; i++)
{
m_imgTypeList.Draw(pDC, 8 + ((nMode==i && (pItem->GetFinished()))?i+1:0), rcItem.TopLeft(), ILD_NORMAL);
rcItem.left += 16;
}
}
void CDiskListCtrl::DrawDrive(CDC *pDC, const CRect& rcClient, int nItem)
{
CRect rcItem;
CItemInfo* pItem = m_arrayDrive.GetAt(nItem);
// Image
GetItemRect(rcClient, rcItem, nItem, 0);
rcItem.left += (rcItem.Width() - 16) / 2;
rcItem.top += (rcItem.Height() - 16) / 2;
switch (pItem->m_nDriveType)
{
case DRIVE_REMOVABLE:
m_imgTypeList.Draw(pDC, 0, rcItem.TopLeft(), ILD_NORMAL);
break;
case DRIVE_FIXED:
m_imgTypeList.Draw(pDC, 1, rcItem.TopLeft(), ILD_NORMAL);
break;
case DRIVE_REMOTE:
if (pItem->m_bAvailable)
m_imgTypeList.Draw(pDC, 3, rcItem.TopLeft(), ILD_NORMAL);
else
m_imgTypeList.Draw(pDC, 4, rcItem.TopLeft(), ILD_NORMAL);
break;
case DRIVE_CDROM:
m_imgTypeList.Draw(pDC, 2, rcItem.TopLeft(), ILD_NORMAL);
break;
case DRIVE_RAMDISK:
m_imgTypeList.Draw(pDC, 5, rcItem.TopLeft(), ILD_NORMAL);
break;
}
CString str, strText;
if (pItem->m_bAvailable)
{
// Draw Title
GetItemRect(rcClient, rcItem, nItem, 1);
pDC->DrawText(pItem->m_strTitle, rcItem, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
//Draw Type
GetItemRect(rcClient, rcItem, nItem, 2);
pDC->DrawText(pItem->m_strPartitionType, rcItem, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
// Total
GetItemRect(rcClient, rcItem, nItem, 3);
//rcItem.right-=10;
FormatByteSize(pItem->m_ldTotalSpace, str);
pDC->DrawText(str, rcItem, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
long double ldUsed = pItem->m_ldTotalSpace - pItem->m_ldFreeSpace;
// Draw Usage
GetItemRect(rcClient, rcItem, nItem, 4);
rcItem.DeflateRect(0, 2);
str.Format("%.0f%%", pItem->GetUsage() * 100);
DrawPercentBar(pDC, rcItem, pItem->GetUsage(),
str, GetFont());
// Used
GetItemRect(rcClient, rcItem, nItem, 5);
FormatByteSize(ldUsed, str);
pDC->DrawText(str, rcItem, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
// Free in bold font
GetItemRect(rcClient, rcItem, nItem, 6);
FormatByteSize(pItem->m_ldFreeSpace, str);
pDC->DrawText(str, rcItem, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
}else
{
if (pItem->m_nDriveType == DRIVE_CDROM ||
pItem->m_nDriveType == DRIVE_REMOVABLE )
str.LoadString(IDS_NODISK);
else
str.LoadString(IDS_NOTAVAILABLE);
strText.Format(str, pItem->m_strDriveName);
GetItemRect(rcClient, rcItem, nItem, -1);
pDC->DrawText(strText, rcItem, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
}
}
void CDiskListCtrl::Update(BOOL bFolders)
{
int nCount = m_arrayDrive.GetSize();
BOOL bUpdate = FALSE;
CItemInfo* pItem;
for (int i = 0; i < nCount; i++)
{
pItem = m_arrayDrive.GetAt(i);
if (pItem->Update())
bUpdate = TRUE;
}
if (bFolders)
{
nCount = m_arrayFolder.GetSize();
for (i = 0; i < nCount; i++)
{
pItem = m_arrayFolder.GetAt(i);
pItem->UpdateFolder(i+100);
}
}
if (bUpdate)
InvalidateRect(NULL, FALSE);
}
int CDiskListCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
InitCtrl();
return 0;
}
void CDiskListCtrl::InitCtrl()
{
// Delete all
if (!m_bmpDriveBack.IsEmpty()) m_bmpDriveBack.DestroyBitmap();
if (!m_bmpFreeBack.IsEmpty()) m_bmpFreeBack.DestroyBitmap();
if (!m_bmpTotalBack.IsEmpty()) m_bmpTotalBack.DestroyBitmap();
if (!m_bmpFolderBack.IsEmpty()) m_bmpFolderBack.DestroyBitmap();
if (!m_bmpHighBack.IsEmpty()) m_bmpHighBack.DestroyBitmap();
if (!m_bmpPressedBack.IsEmpty()) m_bmpPressedBack.DestroyBitmap();
if (m_fontTitle.m_hObject)
m_fontTitle.DeleteObject();
if (m_imgTypeList.m_hImageList)
m_imgTypeList.DeleteImageList();
m_fontTitle.CreateFont(16, 0,0,0,FW_NORMAL, 0,0,0,
DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial");
HINSTANCE hIns = AfxGetResourceHandle();
AfxSetResourceHandle(AfxGetInstanceHandle());
m_imgTypeList.Create(IDB_TYPE_LIST_SMALL, 16, 0, RGB(255,0,255));
AfxSetResourceHandle(hIns);
CWinApp* app = AfxGetApp();
CString strPath = GetHomeDirectory();
m_bEnableBackground = app->GetProfileInt("Settings", "EnableBackground", 1);
CString strBmpDrive = app->GetProfileString("Settings", "BmpDrive", strPath+"images\\Drive.bmp");
CString strBmpFolder = app->GetProfileString("Settings", "BmpFolder", strPath+"images\\Folder.bmp");
CString strBmpFree = app->GetProfileString("Settings", "BmpFree", strPath+"images\\Free.bmp");
CString strBmpHigh = app->GetProfileString("Settings", "BmpHigh", strPath+"images\\High.bmp");
CString strBmpPressed = app->GetProfileString("Settings", "BmpPressed", strPath+"images\\Pressed.bmp");
CString strBmpTotal = app->GetProfileString("Settings", "BmpTotal", strPath+"images\\Total.bmp");
if (m_bEnableBackground)
{
m_bmpDriveBack.Load(strBmpDrive);
m_bmpFreeBack.Load(strBmpFree);
m_bmpTotalBack.Load(strBmpTotal);
m_bmpFolderBack.Load(strBmpFolder);
m_bmpHighBack.Load(strBmpHigh);
m_bmpPressedBack.Load(strBmpPressed);
}
InvalidateRect(NULL, FALSE);
}
void CDiskListCtrl::GetTotalUsage(int& nCount, long double &ldTotal, long double &ldFree)
{
int nSize = m_arrayDrive.GetSize();
ldTotal = 0;
ldFree = 0;
nCount = 0;
for (int i = 0; i < nSize; i++)
{
CItemInfo* pItem = m_arrayDrive.GetAt(i);
if (pItem->m_bAvailable)
{
nCount ++;
ldTotal += pItem->m_ldTotalSpace;
ldFree += pItem->m_ldFreeSpace;
}
}
}
void CDiskListCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
if (GetActiveWindow() == NULL || GetOwner() == NULL)
return;
int nOldCode = m_nMouseInCode;
int nCode = HitTestEx(point);
if (nFlags & MK_LBUTTON)
m_bMouseDown = TRUE;
else
{
m_bMouseDown = FALSE;
m_nMouseDownCode = 1000;
}
if (m_nMouseInCode != nCode)
{
int nOld = m_nMouseInCode;
m_nMouseInCode = nCode;
RedrawItem(nOld);
RedrawItem(m_nMouseInCode);
KillTimer(5);
SetTimer(5,10,NULL);
}
CWnd::OnMouseMove(nFlags, point);
}
void CDiskListCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
if (m_nMouseInCode<1000)
{
int n = HitTestEx(point);
VERIFY(m_nMouseInCode == n);
m_nMouseDownCode = n;
if (!m_bMouseDown)
m_bMouseDown = TRUE;
RedrawItem(m_nMouseInCode);
/*
CRect rcClient, rcItem;
GetClientRect(&rcClient);
GetItemRect(rcClient, rcItem, n, -1);
CString str;
str.Format("%d,%d, %d, %d", rcItem.left, rcItem.top, rcItem.right, rcItem.bottom);
MessageBox(str);
*/
}
CWnd::OnLButtonDown(nFlags, point);
}
void CDiskListCtrl::OnLButtonUp(UINT nFlags, CPoint point)
{
if (m_nMouseInCode<1000 && m_nMouseDownCode== m_nMouseInCode)
{
int n = HitTestEx(point);
if (m_bMouseDown)
{
if (m_nMouseInCode == n)
{
m_bMouseDown = FALSE;
m_nMouseDownCode = 1000;
RedrawItem(m_nMouseInCode);
if (m_nMouseInCode < 0) // Sort
SortItems(-m_nMouseInCode);
else
{
if (m_nMouseInCode>=100)
GetOwner()->SendMessage(WM_DISKLIST_NOTIFY, NULL,
(LPARAM)m_arrayFolder.GetAt(m_nMouseInCode-100));
else
GetOwner()->SendMessage(WM_DISKLIST_NOTIFY, NULL,
(LPARAM)m_arrayDrive.GetAt(m_nMouseInCode));
}
/*
CRect rcClient, rcItem;
GetClientRect(&rcClient);
if (n>=0)
GetItemRect(rcClient, rcItem, n, -1);
else
GetItemRect(rcClient, rcItem, -1, -n);
CString str;
str.Format("Item %d : %d,%d, %d, %d", m_nMouseInCode, rcItem.left, rcItem.top, rcItem.right, rcItem.bottom);
MessageBox(str);*/
}else
{
int nOld = m_nMouseInCode;
m_bMouseDown = FALSE;
m_nMouseInCode = 1000;
m_nMouseDownCode = 1000;
RedrawItem(nOld);
}
}
}else
{
m_bMouseDown = FALSE;
m_nMouseDownCode = 1000;
RedrawItem(m_nMouseInCode);
}
CWnd::OnLButtonUp(nFlags, point);
}
int CDiskListCtrl::HitTestEx(CPoint pt)
{
int nCount = m_arrayDrive.GetSize();
CRect rcClient, rcItem;
GetClientRect(&rcClient);
int nHeight;
if (nCount>0)
{
GetItemRect(rcClient, rcItem, 0, -1);
nHeight = rcItem.Height();
rcItem.bottom += nHeight*(nCount-1);
if (rcItem.PtInRect(pt))
return (pt.y - rcItem.top) / nHeight;
}
//Check Folders
nCount = m_arrayFolder.GetSize();
if (nCount>0)
{
GetItemRect(rcClient, rcItem, 100, -1);
nHeight = rcItem.Height();
rcItem.bottom += nHeight*(nCount-1);
if (rcItem.PtInRect(pt))
return ((pt.y - rcItem.top) / nHeight)+100;
}
/*
for (int i=0; i=100) // Folders
rc.top = nTitleHeight + 1 + nHeight*((nType-100)+(nDriveSize!=0)+nDriveSize);
else
rc.top = nTitleHeight + 1 + nHeight*nType;
rc.bottom = rc.top + nHeight;
}
if (nPos == -1)
return;
// nPos -1 = Max Width
// nPos 0-n = for every column
// nPos in percent
// 4 20 11 15 15,6 15,6 18,8
// 0 <= nCode <= 6
// Drive item rects
if (nType<100)
{
double dWidth[7] = {0.04, 0.242, 0.11, 0.156, 0.14, 0.156, 0.156};
double dOff = 0;
int nTotal = rcC.Width();
for (int i=0; i=0)
{
GetItemRect(rcClient, rcItem, i, -1);
//rcItem.bottom +=2;
InvalidateRect(rcItem, FALSE);
return;
}
// Check Title bar
GetItemRect(rcClient, rcItem, -1, -i);
InvalidateRect(rcItem, FALSE);
}
void CDiskListCtrl::OnTimer(UINT nIDEvent)
{
if (m_nMouseInCode < 1000)
{
CPoint pt;
if (!GetCursorPos(&pt))
return;
ScreenToClient(&pt);
CRect rcClient;
GetClientRect(&rcClient);
if (!rcClient.PtInRect(pt))
{
KillTimer(5);
int nOld = m_nMouseInCode;
m_nMouseInCode = 1000;
//m_bMouseDown = FALSE;
//m_nMouseDownCode = 1000;
RedrawItem(nOld);
}
}
CWnd::OnTimer(nIDEvent);
}
void CDiskListCtrl::SortItems(int n)
{
int nSize = m_arrayDrive.GetSize();
if (nSize>0)
{
if (m_nSortCode == n)
m_nSortCode = -n;
else
m_nSortCode = n;
qsort((void*)(m_arrayDrive.GetData()),
((size_t)nSize),
sizeof(m_arrayDrive.GetAt(0)),
CompareItemSize);
InvalidateRect(NULL, FALSE);
}
}
int CDiskListCtrl::CompareItemSize(const void* f1, const void* f2)
{
CItemInfo* pItem1 = *(CItemInfo**)f1;
CItemInfo* pItem2 = *(CItemInfo**)f2;
if (!pItem2->m_bAvailable && abs(m_nSortCode)!=1)
return -1;
else if (!pItem1->m_bAvailable && abs(m_nSortCode)!=1)
return 1;
switch (m_nSortCode)
{
case 1:
return (long)pItem1->m_strDriveName.CompareNoCase(pItem2->m_strDriveName);
case 2:
return (long)pItem1->m_strPartitionType.CompareNoCase(pItem2->m_strPartitionType);
case 3: // Total
return (int)(pItem1->m_ldTotalSpace/1048576 - pItem2->m_ldTotalSpace/1048576);
case 4: //Usage
return (long)((pItem1->GetUsage() - pItem2->GetUsage())*100);
case 5: // Used
return (long)((pItem1->m_ldTotalSpace - pItem1->m_ldFreeSpace - pItem2->m_ldTotalSpace
+ pItem2->m_ldFreeSpace)/1048576);
case 6: // Free
return (long)((pItem1->m_ldFreeSpace - pItem2->m_ldFreeSpace)/1048576);
case -1:
return (long)pItem2->m_strDriveName.CompareNoCase(pItem1->m_strDriveName);
case -2:
return (long)pItem2->m_strPartitionType.CompareNoCase(pItem1->m_strPartitionType);
case -3: // Total
return (long)(pItem2->m_ldTotalSpace/1048576 - pItem1->m_ldTotalSpace/1048576);
case -4: //Usage
return (long)((pItem2->GetUsage() - pItem1->GetUsage())*100);
case -5: // Used
return (long)((pItem2->m_ldTotalSpace - pItem2->m_ldFreeSpace - pItem1->m_ldTotalSpace
+ pItem1->m_ldFreeSpace)/1048576);
case -6: // Free
return (long)((pItem2->m_ldFreeSpace - pItem1->m_ldFreeSpace)/1048576);
}
return 0;
}
int CDiskListCtrl::GetSize()
{
return m_arrayDrive.GetSize() + m_arrayFolder.GetSize();
}
double CDiskListCtrl::CItemInfo::GetUsage()
{
return (m_ldTotalSpace==0)?0:((m_ldTotalSpace-m_ldFreeSpace)/m_ldTotalSpace);
}
void CDiskListCtrl::CItemInfo::UpdateFolder(int nItemCode)
{
if (m_pThread)
return;
m_nFileCount = 0;
m_nFolderCount = 0;
m_ldTotalSpace = 0; // Numbers of files in folder mode
// Create a process to update folder info
THREADPARAMS* pThreadParams = new THREADPARAMS;
strcpy(pThreadParams->charPath, m_strDriveName);
pThreadParams->nItemCode = nItemCode;
pThreadParams->pnThreadCode = &m_nThreadCode;
pThreadParams->pnFileCount = &m_nFileCount;
pThreadParams->pnFolderCount = &m_nFolderCount;
pThreadParams->pldTotalSpace = &m_ldTotalSpace;
pThreadParams->lParam = (LPARAM)m_pCtrl;
m_pThread = AfxBeginThread(ThreadFunc, pThreadParams, THREAD_PRIORITY_BELOW_NORMAL);
//....
}
UINT CDiskListCtrl::CItemInfo::ThreadFunc(LPVOID pParam)
{
THREADPARAMS* pThreadParams = (THREADPARAMS*)pParam;
/*
CString strPath = pThreadParams->strPath;
int nItemCode = pThreadParams->nItemCode;
int* pnThreadCode = pThreadParams->pnThreadCode;
int* pnFileCount = pThreadParams->pnFileCount;
int* pnFolderCount = pThreadParams->pnFolderCount;
long double* pldTotalSpace = pThreadParams->pldTotalSpace;
CDiskListCtrl* pCtrl = (CDiskListCtrl*)pThreadParams->lParam;
*/
((CDiskListCtrl*)pThreadParams->lParam)->OnStartUpdate(pThreadParams->nItemCode);
UpdateDir(pThreadParams);
((CDiskListCtrl*)pThreadParams->lParam)->PostMessage(WM_DISKLIST_UPDATE, NULL,
LPARAM(pThreadParams->nItemCode));
((CDiskListCtrl*)pThreadParams->lParam)->OnFinishedUpdate(pThreadParams->nItemCode);
delete pThreadParams;
return 0;
}
void CDiskListCtrl::CItemInfo::UpdateDir(THREADPARAMS* pThreadParams)
{
HANDLE hFind;
WIN32_FIND_DATA fd;
char charCmp[MAX_PATH], charPath[MAX_PATH];
strcpy(charPath, pThreadParams->charPath);
strcpy(charCmp, charPath);
strcat(charCmp, "*.*");
if ((hFind = ::FindFirstFile ((LPCTSTR) charCmp, &fd)) ==
INVALID_HANDLE_VALUE)
{
return;
}
do {
if (*(pThreadParams->pnThreadCode) == -1)
break;
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
strcpy(charCmp, (LPCTSTR) &fd.cFileName);
if ((strcmp(charCmp, ".")!=0) && (strcmp(charCmp, "..")!=0))
{
(*(pThreadParams->pnFolderCount)) ++;
strcat(pThreadParams->charPath, charCmp);
strcat(pThreadParams->charPath, "\\");
UpdateDir(pThreadParams);
strcpy(pThreadParams->charPath, charPath);
}
}else
{
(*(pThreadParams->pnFileCount)) ++;
(*(pThreadParams->pldTotalSpace)) += fd.nFileSizeLow;
}
if (*(pThreadParams->pnThreadCode) == -1)
break;
if (((*(pThreadParams->pnFileCount))+(*(pThreadParams->pnFileCount))) % 299 == 0)
{
((CDiskListCtrl*)pThreadParams->lParam)->PostMessage(WM_DISKLIST_UPDATE, NULL,
LPARAM(pThreadParams->nItemCode));
//((CDiskListCtrl*)pThreadParams->lParam)->RedrawItem(pThreadParams->nItemCode);
Sleep(1);
}else
Sleep(0);
} while (::FindNextFile (hFind, &fd));
::FindClose (hFind);
}
void CDiskListCtrl::OnStopAll()
{
int nCount = m_arrayFolder.GetSize();
for (int i = 0; i < nCount; i++)
m_arrayFolder.GetAt(i)->StopThread();
}
void CDiskListCtrl::OnPause()
{
}
void CDiskListCtrl::OnFinishedUpdate(int n)
{
CItemInfo* pItem = m_arrayFolder.GetAt(n-100);
pItem ->m_nThreadCode = 1;
pItem ->m_pThread = NULL;
m_nNrThread --;
RedrawItem(n);
}
void CDiskListCtrl::OnStartUpdate(int n)
{
m_nNrThread ++;
}
void CDiskListCtrl::CItemInfo::StopThread()
{
if (m_pThread)
{
m_nThreadCode = -1;
HANDLE hThread = m_pThread->m_hThread;
::WaitForSingleObject(hThread, INFINITE);
m_pThread = NULL;
m_nFileCount = -1;
}
}
inline BOOL CDiskListCtrl::CItemInfo::GetFinished()
{
return m_nFileCount!=-1;
}
void CDiskListCtrl::UpdateAbortedFolders()
{
int nCount = m_arrayFolder.GetSize();
CItemInfo* pItem;
for (int i = 0; i < nCount; i++)
{
pItem = m_arrayFolder.GetAt(i);
if (!pItem->GetFinished())
pItem->UpdateFolder(i+100);
}
}
void CDiskListCtrl::OnItemUpdate(WPARAM wParam, LPARAM lParam)
{
RedrawItem((int)lParam);
}
void CDiskListCtrl::EmptyFolderArray()
{
int nCount = m_arrayFolder.GetSize();
for (int i = 0; i < nCount; i++)
delete m_arrayFolder.GetAt(i);
m_arrayFolder.RemoveAll();
}