#include <wchar.h>
#include <Windows.h>
#include <CommCtrl.h>
#include "resource.h"
#define SECT L"General"
class WaitCursor {
private:
HCURSOR hPrev;
public:
WaitCursor() {
hPrev = SetCursor(LoadCursor(NULL, IDC_WAIT));
}
~WaitCursor() {
SetCursor(hPrev);
}
};
// 外部変数
HWND hList;
TCHAR szIniFile[MAX_PATH];
TCHAR szSizeMin[16];
TCHAR szSaveDir[MAX_PATH];
TCHAR szContent[MAX_PATH];
// 関数プロトタイプ宣言
void GetIniFileName();
LPTSTR ThousandsSeparator(DWORD dw);
void Trace(LPCTSTR format, ...);
INT_PTR CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void UpdateData(HWND hDlg, BOOL bSave);
void OnInitDialog(HWND hDlg);
void OnDestroy(HWND hDlg);
void OnColumnClick(HWND hDlg, LPNMLISTVIEW plv);
void OnGetList(HWND hDlg);
void OnSave(HWND hDlg);
int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
//==============================================================================
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
GetIniFileName();
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG), NULL, DlgProc);
return 0;
}
void GetIniFileName()
{
TCHAR szPath [_MAX_PATH];
TCHAR szDrive [_MAX_DRIVE];
TCHAR szDir [_MAX_DIR];
TCHAR szFName [_MAX_FNAME];
TCHAR szExt [_MAX_EXT];
GetModuleFileName(NULL, szPath, _countof(szPath));
_wsplitpath_s(szPath, szDrive, szDir, szFName, szExt);
_wmakepath_s(szIniFile, szDrive, szDir, szFName, L"ini");
}
LPTSTR ThousandsSeparator(DWORD dw)
{
static TCHAR szResult[16];
TCHAR szBuf[16];
int nLen = swprintf_s(szBuf, L"%u", dw);
int i = 0;
for (int n = 0; n < nLen; n++) {
szResult[i++] = szBuf[n];
int nPlace = nLen - n;
if (3 < nPlace && (nPlace % 3) == 1) szResult[i++] = L',';
}
szResult[i] = L'\0';
return szResult;
}
void Trace(LPCTSTR format, ...)
{
va_list arg_ptr;
TCHAR buffer[256];
int size;
va_start(arg_ptr, format);
size = _vsnwprintf_s(buffer, _TRUNCATE, format, arg_ptr);
va_end(arg_ptr);
OutputDebugString(buffer);
if (size < 0) {
OutputDebugString(L"...\n");
}
}
//------------------------------------------------------------------------------
INT_PTR CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
INT_PTR res = TRUE; // メッセージを処理した
switch (uMsg) {
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
OnGetList(hDlg);
break;
case IDC_SAVE:
OnSave(hDlg);
break;
case IDCANCEL:
EndDialog(hDlg, IDCANCEL);
break;
}
break;
case WM_NOTIFY:
switch (LOWORD(wParam)) {
case IDC_LIST:
LPNMLISTVIEW plv = (LPNMLISTVIEW)lParam;
switch (plv->hdr.code) {
case LVN_COLUMNCLICK:
OnColumnClick(hDlg, plv);
break;
}
break;
}
break;
case WM_INITDIALOG:
OnInitDialog(hDlg);
break;
case WM_CLOSE:
EndDialog(hDlg, 0);
break;
case WM_DESTROY:
OnDestroy(hDlg);
break;
default:
res = FALSE; // メッセージを処理しなかった
}
return res;
}
void UpdateData(HWND hDlg, BOOL bSave)
{
if (bSave) {
GetDlgItemText(hDlg, IDC_SIZE_MIN, szSizeMin, _countof(szSizeMin));
GetDlgItemText(hDlg, IDC_SAVE_DIR, szSaveDir, _countof(szSaveDir));
} else {
SetDlgItemText(hDlg, IDC_SIZE_MIN, szSizeMin);
SetDlgItemText(hDlg, IDC_SAVE_DIR, szSaveDir);
}
}
void OnInitDialog(HWND hDlg)
{
int nX = GetPrivateProfileInt(SECT, L"X", 100, szIniFile);
int nY = GetPrivateProfileInt(SECT, L"Y", 100, szIniFile);
GetPrivateProfileString(SECT, L"SizeMin", L"", szSizeMin, _countof(szSizeMin), szIniFile);
GetPrivateProfileString(SECT, L"SaveDir", L"", szSaveDir, _countof(szSaveDir), szIniFile);
SetWindowPos(hDlg, HWND_TOP, nX, nY, 0, 0, SWP_NOSIZE);
UpdateData(hDlg, FALSE);
hList = GetDlgItem(hDlg, IDC_LIST);
// リストビュー拡張スタイル
DWORD dwExStyle = ListView_GetExtendedListViewStyle(hList);
dwExStyle |= LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES;
ListView_SetExtendedListViewStyle(hList, dwExStyle);
// 列情報
struct {
int fmt;
int cx;
LPTSTR pszText;
} lvc[] = {
{LVCFMT_LEFT, 20, L""},
{LVCFMT_LEFT, 300, L"名前"},
{LVCFMT_LEFT, 120, L"最終変更日時"},
{LVCFMT_RIGHT, 80, L"サイズ"},
};
LVCOLUMN col;
col.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
for (int n = 0; n < _countof(lvc); n++) {
col.fmt = lvc[n].fmt;
col.cx = lvc[n].cx;
col.pszText = lvc[n].pszText;
col.iSubItem = n;
ListView_InsertColumn(hList, n, &col);
}
}
void OnDestroy(HWND hDlg)
{
RECT rc;
GetWindowRect(hDlg, &rc);
UpdateData(hDlg, TRUE);
TCHAR szBuf[16];
swprintf_s(szBuf, L"%d", rc.left);
WritePrivateProfileString(SECT, L"X", szBuf, szIniFile);
swprintf_s(szBuf, L"%d", rc.top);
WritePrivateProfileString(SECT, L"Y", szBuf, szIniFile);
WritePrivateProfileString(SECT, L"SizeMin", szSizeMin, szIniFile);
WritePrivateProfileString(SECT, L"SaveDir", szSaveDir, szIniFile);
}
void OnColumnClick(HWND hDlg, LPNMLISTVIEW plv)
{
if (plv->iSubItem == 0) {
int n = MessageBox(hDlg, L"はい\t全てチェック\nいいえ\t全てクリア", L"IECacheSave",
MB_YESNOCANCEL | MB_ICONINFORMATION);
if (n == IDCANCEL) return;
BOOL fCheck = (n == IDYES);
int nCount = ListView_GetItemCount(hList);
for (int i = 0; i < nCount; i++) {
ListView_SetCheckState(hList, i, fCheck);
}
} else {
WaitCursor wait;
ListView_SortItems(hList, CompareFunc, plv->iSubItem);
}
}
void OnGetList(HWND hDlg)
{
WaitCursor wait;
TCHAR szBuf[MAX_PATH];
// UpdateData(hDlg, TRUE);
UINT nSizeMin = GetDlgItemInt(hDlg, IDC_SIZE_MIN, NULL, FALSE);
// バージョン情報の取得
OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof vi;
GetVersionEx(&vi);
if (vi.dwMajorVersion == 5) { // 2K, XP
GetEnvironmentVariable(L"USERPROFILE", szContent, _countof(szContent));
wcscat_s(szContent, L"\\Local Settings\\Temporary Internet Files\\Content.IE5");
} else { // Vista, 7
GetEnvironmentVariable(L"LOCALAPPDATA", szContent, _countof(szContent));
wcscat_s(szContent, L"\\Microsoft\\Windows\\Temporary Internet Files\\Low\\Content.IE5");
}
WIN32_FIND_DATA fdm;
swprintf_s(szBuf, L"%s\\*", szContent);
HANDLE hMain = FindFirstFile(szBuf, &fdm);
if (hMain == INVALID_HANDLE_VALUE) return;
// 行情報
LVITEM item;
item.iItem = 0;
ListView_DeleteAllItems(hList);
do {
if ((fdm.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) continue;
if (fdm.cFileName[0] == L'.') continue;
WIN32_FIND_DATA fds;
swprintf_s(szBuf, L"%s\\%s\\*", szContent, fdm.cFileName);
HANDLE hSub = FindFirstFile(szBuf, &fds);
do {
if (fds.nFileSizeLow == 0) continue;
if (fds.nFileSizeLow < nSizeMin) continue;
FILETIME lft;
SYSTEMTIME st;
FileTimeToLocalFileTime(&fds.ftLastWriteTime, &lft);
FileTimeToSystemTime(&lft, &st);
swprintf_s(szBuf, L"%04u/%02u/%02u %02u:%02u:%02u",
st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
item.mask = LVIF_TEXT | LVIF_PARAM;
item.iSubItem = 0;
item.pszText = fdm.cFileName; // SubDir
item.lParam = item.iItem;
ListView_InsertItem(hList, &item);
item.mask = LVIF_TEXT;
item.iSubItem = 1;
item.pszText = fds.cFileName;
ListView_SetItem(hList, &item);
item.iSubItem = 2;
item.pszText = szBuf;
ListView_SetItem(hList, &item);
item.iSubItem = 3;
item.pszText = ThousandsSeparator(fds.nFileSizeLow);
ListView_SetItem(hList, &item);
item.iItem++;
} while (FindNextFile(hSub, &fds));
FindClose(hSub);
} while (FindNextFile(hMain, &fdm));
FindClose(hMain);
// 最終変更日時の降順でソート
ListView_SortItems(hList, CompareFunc, 2);
swprintf_s(szBuf, L"%d 件", item.iItem);
SetDlgItemText(hDlg, IDC_MESSAGE, szBuf);
}
void OnSave(HWND hDlg)
{
WaitCursor wait;
UpdateData(hDlg, TRUE);
TCHAR szNew[_MAX_PATH];
swprintf_s(szNew, L"%s\\%c", szSaveDir, L'\0');
int nCount = ListView_GetItemCount(hList);
for (int i = 0; i < nCount; i++) {
if (ListView_GetCheckState(hList, i)) {
TCHAR szExist [_MAX_PATH];
TCHAR szDir [_MAX_DIR];
TCHAR szFName [_MAX_FNAME];
ListView_GetItemText(hList, i, 0, szDir, _countof(szDir));
ListView_GetItemText(hList, i, 1, szFName, _countof(szFName));
swprintf_s(szExist, L"%s\\%s\\%s%c", szContent, szDir, szFName, L'\0');
// CopyFile(szExist, szNew, TRUE);
SHFILEOPSTRUCT fo;
fo.hwnd = hDlg;
fo.wFunc = FO_COPY;
fo.pFrom = szExist;
fo.pTo = szNew;
fo.fFlags = FOF_ALLOWUNDO;
if (SHFileOperation(&fo)) break;
}
}
}
int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
LVFINDINFO lvfi;
lvfi.flags = LVFI_PARAM;
lvfi.lParam = lParam1;
int iItem1 = ListView_FindItem(hList, -1, &lvfi);
lvfi.lParam = lParam2;
int iItem2 = ListView_FindItem(hList, -1, &lvfi);
TCHAR szBuf1[MAX_PATH];
TCHAR szBuf2[MAX_PATH];
ListView_GetItemText(hList, iItem1, lParamSort, szBuf1, _countof(szBuf1));
ListView_GetItemText(hList, iItem2, lParamSort, szBuf2, _countof(szBuf2));
switch (lParamSort) {
case 1: // 名前
return _wcsicmp(szBuf1, szBuf2);
case 2: // 最終変更日時
return -wcscmp(szBuf1, szBuf2);
case 3: // サイズ
TCHAR szBuf3[16];
TCHAR szBuf4[16];
swprintf_s(szBuf3, L"%13s", szBuf1);
swprintf_s(szBuf4, L"%13s", szBuf2);
return -wcscmp(szBuf3, szBuf4);
}
return 0;
}
// resource script
#include <Windows.h>
#include "resource.h"
IDD_DIALOG DIALOGEX 100, 100, 320, 270
STYLE WS_POPUPWINDOW | WS_MINIMIZEBOX
EXSTYLE WS_EX_APPWINDOW
CAPTION "IECacheSave"
FONT 9, "MS Pゴシック"
BEGIN
CONTROL "",IDC_LIST,"SysListView32",WS_BORDER | WS_TABSTOP | LVS_REPORT,5,5,310,200
LTEXT "サイズ下限",IDC_STATIC,5,213,40,15
EDITTEXT IDC_SIZE_MIN,50,211,45,13
PUSHBUTTON "List(&L)",IDOK,265,210,50,15
LTEXT "保存Dir",IDC_STATIC,5,233,40,15
EDITTEXT IDC_SAVE_DIR,50,231,150,13
// PUSHBUTTON "参照",IDC_SAVE_REF,200,230,30,15
PUSHBUTTON "Copy(&C)",IDC_SAVE,265,230,50,15
LTEXT "",IDC_MESSAGE,5,253,310,15
END