mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 04:36:40 +00:00
enhanced file sytem icon cache
svn path=/trunk/; revision=7452
This commit is contained in:
parent
fc05db5095
commit
42a645bad5
4 changed files with 127 additions and 104 deletions
|
@ -172,6 +172,55 @@ void IconCache::init()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Icon& IconCache::extract(String path)
|
||||||
|
{
|
||||||
|
#ifndef __WINE__ ///@todo
|
||||||
|
_tcslwr((LPTSTR)path.c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PathMap::iterator found = _pathMap.find(path);
|
||||||
|
|
||||||
|
if (found != _pathMap.end())
|
||||||
|
return _icons[found->second];
|
||||||
|
|
||||||
|
SHFILEINFO sfi;
|
||||||
|
|
||||||
|
if (SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_ICON|SHGFI_SMALLICON)) { //@@ besser SHGFI_SYSICONINDEX ?
|
||||||
|
const Icon& icon = add(sfi.hIcon, IT_CACHED);
|
||||||
|
|
||||||
|
///@todo limit cache size
|
||||||
|
_pathMap[path] = icon._id;
|
||||||
|
|
||||||
|
return icon;
|
||||||
|
} else
|
||||||
|
return _icons[ICID_NONE];
|
||||||
|
}
|
||||||
|
|
||||||
|
const Icon& IconCache::extract(LPCTSTR path, int idx)
|
||||||
|
{
|
||||||
|
CachePair key(path, idx);
|
||||||
|
|
||||||
|
#ifndef __WINE__ ///@todo
|
||||||
|
_tcslwr((LPTSTR)key.first.c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PathIdxMap::iterator found = _pathIdxMap.find(key);
|
||||||
|
|
||||||
|
if (found != _pathIdxMap.end())
|
||||||
|
return _icons[found->second];
|
||||||
|
|
||||||
|
HICON hIcon;
|
||||||
|
|
||||||
|
if ((int)ExtractIconEx(path, idx, NULL, &hIcon, 1) > 0) {
|
||||||
|
const Icon& icon = add(hIcon, IT_CACHED);
|
||||||
|
|
||||||
|
_pathIdxMap[key] = icon._id;
|
||||||
|
|
||||||
|
return icon;
|
||||||
|
} else
|
||||||
|
return _icons[ICID_NONE];
|
||||||
|
}
|
||||||
|
|
||||||
const Icon& IconCache::extract(IExtractIcon* pExtract, LPCTSTR path, int idx)
|
const Icon& IconCache::extract(IExtractIcon* pExtract, LPCTSTR path, int idx)
|
||||||
{
|
{
|
||||||
HICON hIconLarge = 0;
|
HICON hIconLarge = 0;
|
||||||
|
@ -190,43 +239,11 @@ const Icon& IconCache::extract(IExtractIcon* pExtract, LPCTSTR path, int idx)
|
||||||
return _icons[ICID_NONE];
|
return _icons[ICID_NONE];
|
||||||
}
|
}
|
||||||
|
|
||||||
const Icon& IconCache::extract_from_file(LPCTSTR path, int idx)
|
const Icon& IconCache::add(HICON hIcon, ICON_TYPE type)
|
||||||
{
|
|
||||||
CachePair key(path, idx);
|
|
||||||
|
|
||||||
#ifndef __WINE__ ///@todo
|
|
||||||
_tcslwr((LPTSTR)key.first.c_str());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CacheMap::iterator found = _cache_map.find(key);
|
|
||||||
|
|
||||||
if (found != _cache_map.end())
|
|
||||||
return _icons[found->second];
|
|
||||||
|
|
||||||
HICON hIcon;
|
|
||||||
|
|
||||||
if ((int)ExtractIconEx(path, idx, NULL, &hIcon, 1) > 0) {
|
|
||||||
const Icon& icon = add_cached(hIcon, path, idx);
|
|
||||||
|
|
||||||
_cache_map[key] = icon._id;
|
|
||||||
|
|
||||||
return icon;
|
|
||||||
} else
|
|
||||||
return _icons[ICID_NONE];
|
|
||||||
}
|
|
||||||
|
|
||||||
const Icon& IconCache::add(HICON hIcon)
|
|
||||||
{
|
{
|
||||||
int id = ++s_next_id;
|
int id = ++s_next_id;
|
||||||
|
|
||||||
return _icons[id] = Icon(IT_DYNAMIC, id, hIcon);
|
return _icons[id] = Icon(type, id, hIcon);
|
||||||
}
|
|
||||||
|
|
||||||
const Icon& IconCache::add_cached(HICON hIcon, LPCTSTR path, int idx)
|
|
||||||
{
|
|
||||||
int id = ++s_next_id;
|
|
||||||
|
|
||||||
return _icons[id] = Icon(IT_CACHED, id, hIcon);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Icon& IconCache::get_icon(int id)
|
const Icon& IconCache::get_icon(int id)
|
||||||
|
|
|
@ -85,11 +85,11 @@ struct Icon {
|
||||||
struct IconCache {
|
struct IconCache {
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
|
const Icon& extract(String path);
|
||||||
|
const Icon& extract(LPCTSTR path, int idx);
|
||||||
const Icon& extract(IExtractIcon* pExtract, LPCTSTR path, int idx);
|
const Icon& extract(IExtractIcon* pExtract, LPCTSTR path, int idx);
|
||||||
const Icon& extract_from_file(LPCTSTR path, int idx);
|
|
||||||
|
|
||||||
const Icon& add(HICON hIcon);
|
const Icon& add(HICON hIcon, ICON_TYPE type=IT_DYNAMIC);
|
||||||
const Icon& add_cached(HICON hIcon, LPCTSTR path, int idx);
|
|
||||||
|
|
||||||
const Icon& get_icon(int icon_id);
|
const Icon& get_icon(int icon_id);
|
||||||
HBITMAP get_icon_bitmap(int icon_id, HBRUSH hbrBkgnd, HDC hdc);
|
HBITMAP get_icon_bitmap(int icon_id, HBRUSH hbrBkgnd, HDC hdc);
|
||||||
|
@ -97,15 +97,17 @@ struct IconCache {
|
||||||
void free_icon(int icon_id);
|
void free_icon(int icon_id);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef map<int, Icon> IconMap;
|
|
||||||
|
|
||||||
typedef pair<String, int> CachePair;
|
|
||||||
typedef map<CachePair, ICON_ID> CacheMap;
|
|
||||||
|
|
||||||
static int s_next_id;
|
static int s_next_id;
|
||||||
|
|
||||||
|
typedef map<int, Icon> IconMap;
|
||||||
IconMap _icons;
|
IconMap _icons;
|
||||||
CacheMap _cache_map;
|
|
||||||
|
typedef map<String, ICON_ID> PathMap;
|
||||||
|
PathMap _pathMap;
|
||||||
|
|
||||||
|
typedef pair<String, int> CachePair;
|
||||||
|
typedef map<CachePair, ICON_ID> PathIdxMap;
|
||||||
|
PathIdxMap _pathIdxMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -310,57 +310,62 @@ ShellPath Entry::create_absolute_pidl() const
|
||||||
|
|
||||||
void Entry::extract_icon()
|
void Entry::extract_icon()
|
||||||
{
|
{
|
||||||
|
TCHAR path[MAX_PATH];
|
||||||
|
|
||||||
ICON_ID icon_id = ICID_NONE;
|
ICON_ID icon_id = ICID_NONE;
|
||||||
|
|
||||||
IExtractIcon* pExtract;
|
if (get_path(path))
|
||||||
if (SUCCEEDED(GetUIObjectOf(0, IID_IExtractIcon, (LPVOID*)&pExtract))) {
|
icon_id = g_Globals._icon_cache.extract(path)._id;
|
||||||
TCHAR path[MAX_PATH];
|
|
||||||
unsigned flags;
|
|
||||||
int idx;
|
|
||||||
|
|
||||||
if (SUCCEEDED(pExtract->GetIconLocation(GIL_FORSHELL, path, MAX_PATH, &idx, &flags))) {
|
|
||||||
if (flags & GIL_NOTFILENAME)
|
|
||||||
icon_id = g_Globals._icon_cache.extract(pExtract, path, idx)._id;
|
|
||||||
else {
|
|
||||||
if (idx == -1)
|
|
||||||
idx = 0; // special case for some control panel applications ("System")
|
|
||||||
|
|
||||||
icon_id = g_Globals._icon_cache.extract_from_file(path, idx)._id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* using create_absolute_pidl() [see below] results in more correct icons for some control panel applets ("NVidia").
|
|
||||||
if (icon_id == ICID_NONE) {
|
|
||||||
SHFILEINFO sfi;
|
|
||||||
|
|
||||||
if (SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_ICON|SHGFI_SMALLICON))
|
|
||||||
icon_id = g_Globals._icon_cache.add(sfi.hIcon)._id;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
if (icon_id == ICID_NONE) {
|
|
||||||
LPBYTE b = (LPBYTE) alloca(0x10000);
|
|
||||||
SHFILEINFO sfi;
|
|
||||||
|
|
||||||
FILE* file = fopen(path, "rb");
|
|
||||||
if (file) {
|
|
||||||
int l = fread(b, 1, 0x10000, file);
|
|
||||||
fclose(file);
|
|
||||||
|
|
||||||
if (l)
|
|
||||||
icon_id = g_Globals._icon_cache.add(CreateIconFromResourceEx(b, l, TRUE, 0x00030000, 16, 16, LR_DEFAULTCOLOR));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/ }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (icon_id == ICID_NONE) {
|
if (icon_id == ICID_NONE) {
|
||||||
SHFILEINFO sfi;
|
IExtractIcon* pExtract;
|
||||||
|
if (SUCCEEDED(GetUIObjectOf(0, IID_IExtractIcon, (LPVOID*)&pExtract))) {
|
||||||
|
unsigned flags;
|
||||||
|
int idx;
|
||||||
|
|
||||||
const ShellPath& pidl_abs = create_absolute_pidl();
|
if (SUCCEEDED(pExtract->GetIconLocation(GIL_FORSHELL, path, MAX_PATH, &idx, &flags))) {
|
||||||
LPCITEMIDLIST pidl = pidl_abs;
|
if (flags & GIL_NOTFILENAME)
|
||||||
|
icon_id = g_Globals._icon_cache.extract(pExtract, path, idx)._id;
|
||||||
|
else {
|
||||||
|
if (idx == -1)
|
||||||
|
idx = 0; // special case for some control panel applications ("System")
|
||||||
|
|
||||||
if (SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL|SHGFI_ICON|SHGFI_SMALLICON)) //@@ besser SHGFI_SYSICONINDEX ?
|
icon_id = g_Globals._icon_cache.extract(path, idx)._id;
|
||||||
icon_id = g_Globals._icon_cache.add(sfi.hIcon)._id;
|
}
|
||||||
|
|
||||||
|
/* using create_absolute_pidl() [see below] results in more correct icons for some control panel applets ("NVidia").
|
||||||
|
if (icon_id == ICID_NONE) {
|
||||||
|
SHFILEINFO sfi;
|
||||||
|
|
||||||
|
if (SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_ICON|SHGFI_SMALLICON))
|
||||||
|
icon_id = g_Globals._icon_cache.add(sfi.hIcon)._id;
|
||||||
|
} */
|
||||||
|
/*
|
||||||
|
if (icon_id == ICID_NONE) {
|
||||||
|
LPBYTE b = (LPBYTE) alloca(0x10000);
|
||||||
|
SHFILEINFO sfi;
|
||||||
|
|
||||||
|
FILE* file = fopen(path, "rb");
|
||||||
|
if (file) {
|
||||||
|
int l = fread(b, 1, 0x10000, file);
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
if (l)
|
||||||
|
icon_id = g_Globals._icon_cache.add(CreateIconFromResourceEx(b, l, TRUE, 0x00030000, 16, 16, LR_DEFAULTCOLOR));
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (icon_id == ICID_NONE) {
|
||||||
|
SHFILEINFO sfi;
|
||||||
|
|
||||||
|
const ShellPath& pidl_abs = create_absolute_pidl();
|
||||||
|
LPCITEMIDLIST pidl = pidl_abs;
|
||||||
|
|
||||||
|
if (SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL|SHGFI_ICON|SHGFI_SMALLICON)) //@@ besser SHGFI_SYSICONINDEX ?
|
||||||
|
icon_id = g_Globals._icon_cache.add(sfi.hIcon)._id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_icon_id = icon_id;
|
_icon_id = icon_id;
|
||||||
|
|
|
@ -260,12 +260,6 @@ void ShellDirectory::read_directory(int scan_flags)
|
||||||
|
|
||||||
memcpy(&entry->_data, &w32fd, sizeof(WIN32_FIND_DATA));
|
memcpy(&entry->_data, &w32fd, sizeof(WIN32_FIND_DATA));
|
||||||
|
|
||||||
if (!(w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
|
||||||
if (scan_flags & SCAN_EXTRACT_ICONS)
|
|
||||||
entry->extract_icon();
|
|
||||||
} else
|
|
||||||
entry->_icon_id = ICID_NONE; // don't try again later
|
|
||||||
|
|
||||||
entry->_down = NULL;
|
entry->_down = NULL;
|
||||||
entry->_expanded = false;
|
entry->_expanded = false;
|
||||||
entry->_scanned = false;
|
entry->_scanned = false;
|
||||||
|
@ -315,6 +309,11 @@ void ShellDirectory::read_directory(int scan_flags)
|
||||||
|
|
||||||
entry->_shell_attribs = attribs;
|
entry->_shell_attribs = attribs;
|
||||||
|
|
||||||
|
if (w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
|
entry->_icon_id = ICID_FOLDER;
|
||||||
|
else if (scan_flags & SCAN_EXTRACT_ICONS)
|
||||||
|
entry->extract_icon();
|
||||||
|
|
||||||
last = entry;
|
last = entry;
|
||||||
} while(FindNextFile(hFind, &w32fd));
|
} while(FindNextFile(hFind, &w32fd));
|
||||||
|
|
||||||
|
@ -402,14 +401,6 @@ void ShellDirectory::read_directory(int scan_flags)
|
||||||
entry->_display_name = _tcsdup(name); // store display name separate from file name; sort display by file name
|
entry->_display_name = _tcsdup(name); // store display name separate from file name; sort display by file name
|
||||||
}
|
}
|
||||||
|
|
||||||
// get icons for files and virtual objects
|
|
||||||
if (!(entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
|
|
||||||
!(attribs & SFGAO_FILESYSTEM)) {
|
|
||||||
if (scan_flags & SCAN_EXTRACT_ICONS)
|
|
||||||
entry->extract_icon();
|
|
||||||
} else
|
|
||||||
entry->_icon_id = ICID_NONE; // don't try again later
|
|
||||||
|
|
||||||
entry->_down = NULL;
|
entry->_down = NULL;
|
||||||
entry->_expanded = false;
|
entry->_expanded = false;
|
||||||
entry->_scanned = false;
|
entry->_scanned = false;
|
||||||
|
@ -417,6 +408,16 @@ void ShellDirectory::read_directory(int scan_flags)
|
||||||
entry->_shell_attribs = attribs;
|
entry->_shell_attribs = attribs;
|
||||||
entry->_bhfi_valid = bhfi_valid;
|
entry->_bhfi_valid = bhfi_valid;
|
||||||
|
|
||||||
|
// get icons for files and virtual objects
|
||||||
|
if (!(entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
|
||||||
|
!(attribs & SFGAO_FILESYSTEM)) {
|
||||||
|
if (scan_flags & SCAN_EXTRACT_ICONS)
|
||||||
|
entry->extract_icon();
|
||||||
|
} else if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
|
entry->_icon_id = ICID_FOLDER;
|
||||||
|
else
|
||||||
|
entry->_icon_id = ICID_NONE; // don't try again later
|
||||||
|
|
||||||
last = entry;
|
last = entry;
|
||||||
} catch(COMException& e) {
|
} catch(COMException& e) {
|
||||||
HandleException(e, _hwnd);
|
HandleException(e, _hwnd);
|
||||||
|
@ -470,8 +471,6 @@ int ShellDirectory::extract_icons()
|
||||||
|
|
||||||
if (entry->_icon_id != ICID_NONE)
|
if (entry->_icon_id != ICID_NONE)
|
||||||
++cnt;
|
++cnt;
|
||||||
else
|
|
||||||
entry->_icon_id = ICID_NONE; // don't try again later
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return cnt;
|
return cnt;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue