2013-01-10 05:51:15 +00:00
|
|
|
/*
|
|
|
|
Copyright (C) 2012 Brian Ferguson
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "StdAfx.h"
|
2014-02-07 22:13:13 +00:00
|
|
|
#include <wrl/client.h>
|
2013-01-10 05:51:15 +00:00
|
|
|
|
|
|
|
enum MeasureType
|
|
|
|
{
|
2013-02-28 16:15:28 +00:00
|
|
|
TYPE_FOLDERPATH,
|
|
|
|
TYPE_FOLDERSIZE,
|
|
|
|
TYPE_FILECOUNT,
|
|
|
|
TYPE_FOLDERCOUNT,
|
|
|
|
TYPE_FILENAME,
|
|
|
|
TYPE_FILETYPE,
|
|
|
|
TYPE_FILESIZE,
|
|
|
|
TYPE_FILEDATE,
|
|
|
|
TYPE_FILEPATH,
|
|
|
|
TYPE_ICON
|
2013-01-10 05:51:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
enum DateType
|
|
|
|
{
|
|
|
|
DTYPE_MODIFIED,
|
|
|
|
DTYPE_CREATED,
|
|
|
|
DTYPE_ACCESSED
|
|
|
|
};
|
|
|
|
|
|
|
|
enum SortType
|
|
|
|
{
|
|
|
|
STYPE_NAME,
|
|
|
|
STYPE_SIZE,
|
|
|
|
STYPE_TYPE,
|
|
|
|
STYPE_DATE
|
|
|
|
};
|
|
|
|
|
|
|
|
enum IconSize
|
|
|
|
{
|
|
|
|
IS_SMALL = 1, // 16x16
|
|
|
|
IS_MEDIUM = 0, // 32x32
|
|
|
|
IS_LARGE = 2, // 48x48
|
|
|
|
IS_EXLARGE = 4 // 256x256
|
|
|
|
};
|
|
|
|
|
2013-02-28 16:15:28 +00:00
|
|
|
enum RecursiveType
|
|
|
|
{
|
|
|
|
RECURSIVE_NONE,
|
|
|
|
RECURSIVE_PARTIAL,
|
|
|
|
RECURSIVE_FULL
|
|
|
|
};
|
|
|
|
|
2013-01-10 05:51:15 +00:00
|
|
|
struct FileInfo
|
|
|
|
{
|
|
|
|
std::wstring fileName;
|
2013-02-28 16:15:28 +00:00
|
|
|
std::wstring path;
|
2013-01-10 05:51:15 +00:00
|
|
|
std::wstring ext;
|
|
|
|
bool isFolder;
|
|
|
|
UINT64 size;
|
|
|
|
FILETIME createdTime;
|
|
|
|
FILETIME modifiedTime;
|
|
|
|
FILETIME accessedTime;
|
|
|
|
|
2013-02-28 16:15:28 +00:00
|
|
|
FileInfo() :
|
|
|
|
fileName(L""),
|
|
|
|
path(L""),
|
|
|
|
ext(L""),
|
|
|
|
isFolder(false),
|
|
|
|
size(0),
|
|
|
|
createdTime(),
|
|
|
|
modifiedTime(),
|
|
|
|
accessedTime() { }
|
2013-01-10 05:51:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ChildMeasure;
|
|
|
|
|
|
|
|
struct ParentMeasure
|
|
|
|
{
|
|
|
|
std::wstring path;
|
|
|
|
std::wstring wildcardSearch;
|
|
|
|
SortType sortType;
|
|
|
|
DateType sortDateType;
|
|
|
|
int count;
|
2013-02-28 16:15:28 +00:00
|
|
|
RecursiveType recursiveType;
|
2013-01-10 05:51:15 +00:00
|
|
|
bool sortAscending;
|
|
|
|
bool showDotDot;
|
|
|
|
bool showFile;
|
|
|
|
bool showFolder;
|
|
|
|
bool showHidden;
|
|
|
|
bool showSystem;
|
|
|
|
bool hideExtension;
|
2013-02-28 16:15:28 +00:00
|
|
|
std::vector<std::wstring> extensions;
|
2013-01-16 22:21:17 +00:00
|
|
|
std::wstring finishAction;
|
2013-01-10 05:51:15 +00:00
|
|
|
|
2013-02-28 16:15:28 +00:00
|
|
|
std::vector<ChildMeasure*> iconChildren;
|
2013-01-10 05:51:15 +00:00
|
|
|
std::vector<FileInfo> files;
|
|
|
|
int fileCount;
|
|
|
|
int folderCount;
|
|
|
|
UINT64 folderSize;
|
|
|
|
bool needsUpdating;
|
|
|
|
bool needsIcons;
|
|
|
|
int indexOffset;
|
2013-03-23 16:17:48 +00:00
|
|
|
HANDLE thread;
|
2013-01-10 05:51:15 +00:00
|
|
|
|
2014-02-07 19:34:16 +00:00
|
|
|
void* rm;
|
|
|
|
HWND hwnd;
|
2013-01-10 05:51:15 +00:00
|
|
|
void* skin;
|
|
|
|
LPCWSTR name;
|
|
|
|
ChildMeasure* ownerChild;
|
|
|
|
|
|
|
|
ParentMeasure() :
|
2013-03-21 13:00:33 +00:00
|
|
|
path(),
|
|
|
|
wildcardSearch(),
|
2013-01-10 05:51:15 +00:00
|
|
|
folderSize(0),
|
|
|
|
sortType(STYPE_NAME),
|
|
|
|
sortDateType(DTYPE_MODIFIED),
|
|
|
|
count(0),
|
|
|
|
sortAscending(true),
|
|
|
|
showDotDot(true),
|
|
|
|
showFile(true),
|
|
|
|
showFolder(true),
|
|
|
|
showHidden(true),
|
|
|
|
showSystem(false),
|
|
|
|
hideExtension(false),
|
|
|
|
extensions(),
|
2013-01-16 22:21:17 +00:00
|
|
|
finishAction(),
|
2013-02-28 16:15:28 +00:00
|
|
|
iconChildren(),
|
|
|
|
files(),
|
|
|
|
skin(nullptr),
|
2013-03-21 13:00:33 +00:00
|
|
|
name(),
|
2013-02-28 16:15:28 +00:00
|
|
|
ownerChild(nullptr),
|
2014-02-07 19:34:16 +00:00
|
|
|
rm(),
|
|
|
|
hwnd(),
|
2013-03-23 16:17:48 +00:00
|
|
|
thread(nullptr),
|
2013-01-10 05:51:15 +00:00
|
|
|
fileCount(0),
|
|
|
|
folderCount(0),
|
|
|
|
needsUpdating(true),
|
|
|
|
needsIcons(true),
|
|
|
|
indexOffset(0),
|
2013-02-28 16:15:28 +00:00
|
|
|
recursiveType(RECURSIVE_NONE) { }
|
2013-01-10 05:51:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ChildMeasure
|
|
|
|
{
|
|
|
|
MeasureType type;
|
|
|
|
DateType date;
|
|
|
|
IconSize iconSize;
|
|
|
|
std::wstring iconPath;
|
|
|
|
int index;
|
|
|
|
bool ignoreCount;
|
|
|
|
|
2013-02-28 16:15:28 +00:00
|
|
|
std::wstring strValue;
|
2013-01-10 05:51:15 +00:00
|
|
|
ParentMeasure* parent;
|
|
|
|
|
|
|
|
ChildMeasure() :
|
|
|
|
type(TYPE_FOLDERPATH),
|
|
|
|
date(DTYPE_MODIFIED),
|
|
|
|
iconSize(IS_LARGE),
|
2013-03-21 13:00:33 +00:00
|
|
|
iconPath(),
|
2013-01-10 16:38:55 +00:00
|
|
|
index(1),
|
2013-01-10 05:51:15 +00:00
|
|
|
ignoreCount(false),
|
2013-03-21 13:00:33 +00:00
|
|
|
strValue(),
|
2013-02-28 16:15:28 +00:00
|
|
|
parent(nullptr) { }
|
2013-01-10 05:51:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
std::vector<std::wstring> Tokenize(const std::wstring& str, const std::wstring& delimiters)
|
|
|
|
{
|
|
|
|
std::vector<std::wstring> tokens;
|
|
|
|
|
2013-02-28 16:15:28 +00:00
|
|
|
std::wstring::size_type lastPos = str.find_first_not_of(delimiters, 0);
|
|
|
|
std::wstring::size_type pos = str.find_first_of(delimiters, lastPos);
|
2013-01-10 05:51:15 +00:00
|
|
|
|
|
|
|
while (std::wstring::npos != pos || std::wstring::npos != lastPos)
|
|
|
|
{
|
2013-02-28 16:15:28 +00:00
|
|
|
tokens.emplace_back(str.substr(lastPos, pos - lastPos));
|
|
|
|
lastPos = str.find_first_not_of(delimiters, pos);
|
|
|
|
pos = str.find_first_of(delimiters, lastPos);
|
2013-01-10 05:51:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return tokens;
|
|
|
|
}
|
|
|
|
|
2014-02-07 19:34:16 +00:00
|
|
|
void GetParentFolder(std::wstring& path)
|
|
|
|
{
|
|
|
|
std::vector<std::wstring> tokens = Tokenize(path, L"\\");
|
|
|
|
if (tokens.size() < 2)
|
|
|
|
{
|
|
|
|
path.clear();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
path.clear();
|
|
|
|
for (size_t i = 0; i < tokens.size() - 1; ++i)
|
|
|
|
{
|
|
|
|
path += tokens[i];
|
|
|
|
path += L"\\";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ShowContextMenu(HWND hwnd, std::wstring& path)
|
|
|
|
{
|
|
|
|
POINT pos;
|
|
|
|
GetCursorPos(&pos);
|
|
|
|
|
|
|
|
// If the mouse is outside of the boundaries of
|
|
|
|
// the skin, use the upper-left corner of the skin
|
|
|
|
RECT rect;
|
|
|
|
GetWindowRect(hwnd, &rect);
|
|
|
|
if (pos.x < rect.left || pos.x > rect.right ||
|
|
|
|
pos.y < rect.top || pos.y > rect.bottom)
|
|
|
|
{
|
|
|
|
pos.x = rect.left;
|
|
|
|
pos.y = rect.top;
|
|
|
|
}
|
|
|
|
|
|
|
|
ITEMIDLIST* id = nullptr;
|
|
|
|
HRESULT result = SHParseDisplayName(path.c_str(), nullptr, &id, 0, nullptr);
|
|
|
|
if (!SUCCEEDED(result) || !id)
|
|
|
|
return false;
|
|
|
|
|
2014-02-07 22:13:13 +00:00
|
|
|
Microsoft::WRL::ComPtr<IShellFolder> iFolder = nullptr;
|
2014-02-07 19:34:16 +00:00
|
|
|
LPCITEMIDLIST idChild = nullptr;
|
|
|
|
result = SHBindToParent(id, IID_IShellFolder, (void**)&iFolder, &idChild);
|
|
|
|
if (!SUCCEEDED(result) || !iFolder)
|
|
|
|
return false;
|
|
|
|
|
2014-02-07 22:13:13 +00:00
|
|
|
Microsoft::WRL::ComPtr<IContextMenu> iMenu = nullptr;
|
2014-02-07 19:34:16 +00:00
|
|
|
result = iFolder->GetUIObjectOf(hwnd, 1, (const ITEMIDLIST **)&idChild, IID_IContextMenu, nullptr, (void**)&iMenu);
|
|
|
|
if (!SUCCEEDED(result) || !iFolder)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
HMENU hMenu = CreatePopupMenu();
|
|
|
|
if (!hMenu)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (SUCCEEDED(iMenu->QueryContextMenu(hMenu, 0, 1, 0x7FFF, CMF_NORMAL)))
|
|
|
|
{
|
|
|
|
int iCmd = TrackPopupMenuEx(hMenu, TPM_RETURNCMD, pos.x, pos.y, hwnd, NULL);
|
|
|
|
if (iCmd > 0)
|
|
|
|
{
|
|
|
|
CMINVOKECOMMANDINFOEX info = { 0 };
|
|
|
|
info.cbSize = sizeof(info);
|
|
|
|
info.fMask = CMIC_MASK_UNICODE | CMIC_MASK_ASYNCOK;
|
|
|
|
info.hwnd = hwnd;
|
|
|
|
info.lpVerb = MAKEINTRESOURCEA(iCmd - 1);
|
|
|
|
info.lpVerbW = MAKEINTRESOURCEW(iCmd - 1);
|
|
|
|
info.nShow = SW_SHOWNORMAL;
|
|
|
|
|
|
|
|
iMenu->InvokeCommand((LPCMINVOKECOMMANDINFO)&info);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DestroyMenu(hMenu);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-01-10 05:51:15 +00:00
|
|
|
/*std::wstring UINT64_To_String(UINT64 value)
|
|
|
|
{
|
|
|
|
std::wstring result;
|
|
|
|
result.reserve(20); // Max of 20 digits possible
|
|
|
|
do
|
|
|
|
{
|
|
|
|
result += "0123456789"[value % 10];
|
|
|
|
value /= 10;
|
|
|
|
}
|
|
|
|
while(value);
|
|
|
|
|
|
|
|
std::reverse(result.begin(), result.end());
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}*/
|