Introduction
Don't tell me you never had to right click a folder only to
see in the properties the size of the content. If you never did it, skip reading
this article!!!
Let's take a look at the code
If you did it, what you need is a shell
extension!!! What is a shell extension? You will find the right answer reading
The Michael Dunn's Complete Idiot's Guide to Writing Shell Extensions,
here on CodeProject. What I did is read the
Part VIII of the series
and modify two functions to get my content-size-column in the Explorer. First of
all, I did all the building without the last Platform SDK. So, I
needed to add manually to my code the
IColumnProvider
interface
declaration, plus some other declarations in my header files, like this
typedef struct {
GUID fmtid;
DWORD pid;
} SHCOLUMNID, *LPSHCOLUMNID;
typedef const SHCOLUMNID* LPCSHCOLUMNID;
typedef struct {
ULONG dwFlags;
ULONG dwReserved;
WCHAR wszFolder[MAX_PATH];
} SHCOLUMNINIT, *LPSHCOLUMNINIT;
#define MAX_COLUMN_NAME_LEN 80
#define MAX_COLUMN_DESC_LEN 128
#pragma pack(1)
typedef struct {
SHCOLUMNID scid;
VARTYPE vt;
DWORD fmt;
UINT cChars;
DWORD csFlags;
WCHAR wszTitle[MAX_COLUMN_NAME_LEN];
WCHAR wszDescription[MAX_COLUMN_DESC_LEN];
} SHCOLUMNINFO, *LPSHCOLUMNINFO;
#define SHCDF_UPDATEITEM 0x00000001
typedef struct {
ULONG dwFlags;
DWORD dwFileAttributes;
ULONG dwReserved;
WCHAR *pwszExt;
WCHAR wszFile[MAX_PATH];
} SHCOLUMNDATA, *LPSHCOLUMNDATA;
typedef const SHCOLUMNDATA* LPCSHCOLUMNDATA;
DECLARE_INTERFACE_(IColumnProvider, IUnknown)
{
STDMETHOD (QueryInterface)(THIS_ REFIID riid, void **ppv) PURE;
STDMETHOD_(ULONG, AddRef)(THIS) PURE;
STDMETHOD_(ULONG, Release)(THIS) PURE;
STDMETHOD (Initialize)(THIS_ LPSHCOLUMNINIT psci) PURE;
STDMETHOD (GetColumnInfo)(THIS_ DWORD dwIndex, LPSHCOLUMNINFO psci) PURE;
STDMETHOD (GetItemData)(THIS_ LPCSHCOLUMNID pscid, LPCSHCOLUMNDATA pscd,
VARIANT *pvarData) PURE;
};
Remember to remove all this code (in
DirSizeColumn.h) if you have the right Platform SDK or you'll get some
compiler error. The core of the dll are the two functions
CDirSizeColumn::GetColumnInfo
and
CDirSizeColumn::GetItemData
. The first tells Explorer that there
will be a new column, right aligned etc etc:
STDMETHODIMP CDirSizeColumn::GetColumnInfo ( DWORD dwIndex,
LPSHCOLUMNINFO psci )
{
HRESULT hRes=S_FALSE;
if (dwIndex==0)
{
psci->scid.fmtid = *_Module.pguidVer;
psci->scid.pid = MY_COLUMN_ID;
psci->vt = VT_LPSTR;
psci->fmt = LVCFMT_RIGHT;
psci->csFlags = 0x22;
psci->cChars = 6;
lstrcpyW ( psci->wszTitle, L"Content Size\0");
lstrcpyW ( psci->wszDescription,
L"Size of all files and subfolders contained\0");
hRes=S_OK;
}
return hRes;
}
The second one will do the calc stuff for any directory being passed as
param
STDMETHODIMP CDirSizeColumn::GetItemData (
LPCSHCOLUMNID pscid,
LPCSHCOLUMNDATA pscd,
VARIANT* pvarData )
{
HRESULT hRes=S_FALSE;
if ( pscid->fmtid == *_Module.pguidVer )
{
if ( (pscd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)==
FILE_ATTRIBUTE_DIRECTORY)
{
if ( pscid->pid == MY_COLUMN_ID )
{
CString strFileName(pscd->wszFile);
char szText[100];
sprintf(szText,"%I64d KB",(__int64)(
GetDirSize(strFileName)/(__int64)1024));
CComVariant vData(szText);
vData.Detach ( pvarData );
hRes=S_OK;
}
}
}
return hRes;
}
Really simple, isn't it? :) The function that read folders size is a
simple recursive function, uses
CFileFind
from MFC and iterate in
any subfolder and any file in a given folder.
__int64 GetDirSize(CString strFileName)
{
__int64 i64Size=0;
TRY
{
CFileFind finder;
BOOL bWorking = finder.FindFile(strFileName+"\\*.*");
while (bWorking)
{
bWorking = finder.FindNextFile();
if (!finder.IsDots())
{
if (finder.IsDirectory())
i64Size=i64Size+GetDirSize(finder.GetFilePath());
else
i64Size=i64Size+finder.GetLength64();
}
}
}
CATCH(CException, ex)
{
i64Size=0;
}
END_CATCH
return i64Size;
}
Install/Uninstall
To install the extension use the following command:
regsvr32 SHDireSizeColumn.dll
and to uninstall, type:
regsvr32 /u SHDireSizeColumn.dll
Remember to close all
Explorer windows and next time you want to know the size of the content of a dir
you will have to right click etc etc etc... :)
And then...
Many many thanks to Michael Dunn, writing this article has
been a matter of minutes once I read his guides!!! :) See you soon.