#include <wchar.h>
#include <Windows.h>
#include <CommCtrl.h>
#include <VersionHelpers.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 szExtension[256];
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);
BOOL CheckExt(LPCTSTR filename, LPCTSTR extension);
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 path[_MAX_PATH];
TCHAR drive[_MAX_DRIVE];
TCHAR dir[_MAX_DIR];
TCHAR fname[_MAX_FNAME];
TCHAR ext[_MAX_EXT];
GetModuleFileName(NULL, path, _countof(path));
_wsplitpath_s(path, drive, dir, fname, ext);
_wmakepath_s(szIniFile, drive, dir, fname, 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 NM_CLICK:
if (0 <= plv->iItem && 0 < plv->iSubItem) {
BOOL fCheck = ListView_GetCheckState(hList, plv->iItem);
ListView_SetCheckState(hList, plv->iItem, fCheck ? FALSE : TRUE);
}
break;
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_EXTENSION, szExtension, _countof(szExtension));
GetDlgItemText(hDlg, IDC_SAVE_DIR, szSaveDir, _countof(szSaveDir));
}
else {
SetDlgItemText(hDlg, IDC_SIZE_MIN, szSizeMin);
SetDlgItemText(hDlg, IDC_EXTENSION, szExtension);
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"Extension", L"", szExtension, _countof(szExtension), 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 = LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES;
ListView_SetExtendedListViewStyleEx(hList, dwExStyle, 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"Extension", szExtension, 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];
TCHAR szExt[256];
// UpdateData(hDlg, TRUE);
UINT nSizeMin = GetDlgItemInt(hDlg, IDC_SIZE_MIN, NULL, FALSE);
GetDlgItemText(hDlg, IDC_EXTENSION, szExt, _countof(szExt));
// インターネット一時ファイルの場所
if (IsWindows8OrGreater()) {
GetEnvironmentVariable(L"LOCALAPPDATA", szContent, _countof(szContent));
wcscat_s(szContent, L"\\Microsoft\\Windows\\INetCache\\Low\\IE");
}
else if (IsWindowsVistaOrGreater()) {
GetEnvironmentVariable(L"LOCALAPPDATA", szContent, _countof(szContent));
wcscat_s(szContent, L"\\Microsoft\\Windows\\Temporary Internet Files\\Low\\Content.IE5");
}
else {
GetEnvironmentVariable(L"USERPROFILE", szContent, _countof(szContent));
wcscat_s(szContent, L"\\Local Settings\\Temporary Internet Files\\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;
if (CheckExt(fds.cFileName, szExt) == FALSE) 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);
}
BOOL CheckExt(LPCTSTR filename, LPCTSTR extension)
{
if (extension[0] == L'\0') return TRUE;
TCHAR ext[_MAX_EXT];
_wsplitpath_s(filename, NULL, 0, NULL, 0, NULL, 0, ext, _countof(ext));
if (ext[0] != L'.') return FALSE;
if (_wcsicmp(extension, ext + 1) == 0) return TRUE;
return FALSE;
}
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, 290
STYLE WS_POPUPWINDOW | WS_MINIMIZEBOX
EXSTYLE WS_EX_APPWINDOW
CAPTION "IECacheList"
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
LTEXT "拡張子", IDC_STATIC, 5, 233, 40, 15
EDITTEXT IDC_EXTENSION, 50, 231, 150, 13
LTEXT "保存Dir", IDC_STATIC, 5, 253, 40, 15
EDITTEXT IDC_SAVE_DIR, 50, 251, 150, 13
// PUSHBUTTON "参照",IDC_SAVE_REF, 200, 250, 30, 15
LTEXT "", IDC_MESSAGE, 5, 273, 310, 15
PUSHBUTTON "List(&L)", IDOK, 265, 210, 50, 15
PUSHBUTTON "Copy(&C)", IDC_SAVE, 265, 230, 50, 15
END