use system image list instead of discrete icons as far as possible

svn path=/trunk/; revision=7591
This commit is contained in:
Martin Fuchs 2004-01-12 23:03:38 +00:00
parent f4ee51ec85
commit 27e99ffec4
8 changed files with 140 additions and 66 deletions

View file

@ -94,7 +94,7 @@ void CollectProgramsThread::free_dirs()
FindProgramDlg::FindProgramDlg(HWND hwnd)
: super(hwnd),
_list_ctrl(GetDlgItem(hwnd, IDC_MAILS_FOUND)),
_himl(ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32, 0, 0)),
//_himl(ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLOR32, 0, 0)),
_thread(collect_programs_callback, hwnd, this),
_sort(_list_ctrl, CompareFunc/*, (LPARAM)this*/)
{
@ -107,8 +107,9 @@ FindProgramDlg::FindProgramDlg(HWND hwnd)
_haccel = LoadAccelerators(g_Globals._hInstance, MAKEINTRESOURCE(IDA_SEARCH_PROGRAM));
ListView_SetImageList(_list_ctrl, _himl, LVSIL_SMALL);
_idxNoIcon = ImageList_AddIcon(_himl, SmallIcon(IDI_APPICON));
ListView_SetImageList(_list_ctrl, g_Globals._icon_cache.get_sys_imagelist(), LVSIL_SMALL);
//ListView_SetImageList(_list_ctrl, _himl, LVSIL_SMALL);
//_idxNoIcon = ImageList_AddIcon(_himl, SmallIcon(IDI_APPICON));
LV_COLUMN column = {LVCF_FMT|LVCF_WIDTH|LVCF_TEXT, LVCFMT_LEFT, 250};
@ -140,7 +141,7 @@ FindProgramDlg::FindProgramDlg(HWND hwnd)
FindProgramDlg::~FindProgramDlg()
{
ImageList_Destroy(_himl);
//ImageList_Destroy(_himl);
}
@ -315,7 +316,7 @@ int FindProgramDlg::Notify(int id, NMHDR* pnmh)
if (entry->_icon_id == ICID_UNKNOWN)
entry->extract_icon();
pDispInfo->item.iImage = ImageList_AddIcon(_himl, g_Globals._icon_cache.get_icon(entry->_icon_id)._hIcon); //@@ directly use image list in icon cache
pDispInfo->item.iImage = g_Globals._icon_cache.get_icon(entry->_icon_id).get_sysiml_idx();//ImageList_AddIcon(_himl, g_Globals._icon_cache.get_icon(entry->_icon_id).get_hicon());
pDispInfo->item.mask |= LVIF_DI_SETITEM;
return 1;

View file

@ -88,8 +88,8 @@ protected:
CommonControlInit _usingCmnCtrl;
HWND _list_ctrl;
HACCEL _haccel;
HIMAGELIST _himl;
int _idxNoIcon; // replacement icon
//HIMAGELIST _himl;
//int _idxNoIcon; // replacement icon
String _lwr_filter;
CollectProgramsThread _thread;

View file

@ -126,31 +126,80 @@ const FileTypeInfo& FileTypeManager::operator[](String ext)
Icon::Icon()
: _id(ICID_UNKNOWN),
_itype(IT_STATIC),
_hIcon(0)
_hicon(0)
{
}
Icon::Icon(ICON_ID id, UINT nid)
: _id(id),
_itype(IT_STATIC),
_hIcon(SmallIcon(nid))
_hicon(SmallIcon(nid))
{
}
Icon::Icon(ICON_TYPE itype, int id, HICON hIcon)
: _id((ICON_ID)id),
_itype(itype),
_hIcon(hIcon)
_hicon(hIcon)
{
}
Icon::Icon(ICON_TYPE itype, int id, int sys_idx)
: _id((ICON_ID)id),
_itype(itype),
_sys_idx(sys_idx)
{
}
void Icon::draw(HDC hdc, int x, int y, int cx, int cy, COLORREF bk_color, HBRUSH bk_brush) const
{
if (_itype == IT_SYSCACHE)
ImageList_DrawEx(g_Globals._icon_cache.get_sys_imagelist(), _sys_idx, hdc, x, y, cx, cy, bk_color, CLR_DEFAULT, ILD_NORMAL);
else
DrawIconEx(hdc, x, y, _hicon, cx, cy, 0, bk_brush, DI_NORMAL);
}
HBITMAP Icon::create_bitmap(COLORREF bk_color, HBRUSH hbrBkgnd, HDC hdc_wnd) const
{
if (_itype == IT_SYSCACHE) {
HIMAGELIST himl = g_Globals._icon_cache.get_sys_imagelist();
int cx, cy;
ImageList_GetIconSize(himl, &cx, &cy);
HBITMAP hbmp = CreateCompatibleBitmap(hdc_wnd, cx, cy);
HDC hdc = CreateCompatibleDC(hdc_wnd);
HBITMAP hbmp_old = SelectBitmap(hdc, hbmp);
ImageList_DrawEx(himl, _sys_idx, hdc, 0, 0, cx, cy, bk_color, CLR_DEFAULT, ILD_NORMAL);
SelectBitmap(hdc, hbmp_old);
DeleteDC(hdc);
return hbmp;
} else
return create_bitmap_from_icon(_hicon, hbrBkgnd, hdc_wnd);
}
HBITMAP create_bitmap_from_icon(HICON hIcon, HBRUSH hbrush_bkgnd, HDC hdc_wnd)
{
HBITMAP hbmp = CreateCompatibleBitmap(hdc_wnd, 16, 16);
MemCanvas canvas;
BitmapSelection sel(canvas, hbmp);
RECT rect = {0, 0, 16, 16};
FillRect(canvas, &rect, hbrush_bkgnd);
DrawIconEx(canvas, 0, 0, hIcon, 16, 16, 0, hbrush_bkgnd, DI_NORMAL);
return hbmp;
}
int IconCache::s_next_id = ICID_DYNAMIC;
void IconCache::init()
{
_icons[ICID_NONE] = Icon(IT_STATIC, ICID_NONE, 0);
_icons[ICID_NONE] = Icon(IT_STATIC, ICID_NONE, (HICON)0);
_icons[ICID_FOLDER] = Icon(ICID_FOLDER, IDI_FOLDER);
//_icons[ICID_DOCUMENT] = Icon(ICID_DOCUMENT, IDI_DOCUMENT);
@ -181,11 +230,20 @@ const Icon& IconCache::extract(const String& path)
SHFILEINFO sfi;
if (SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_ICON|SHGFI_SMALLICON)) { //@@ besser SHGFI_SYSICONINDEX ?
#if 1 // use system image list
HIMAGELIST himlSys = (HIMAGELIST) SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX|SHGFI_SMALLICON);
if (himlSys) {
_himlSys = himlSys;
const Icon& icon = add(sfi.iIcon/*, IT_SYSCACHE*/);
#else
if (SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_ICON|SHGFI_SMALLICON)) {
const Icon& icon = add(sfi.hIcon, IT_CACHED);
#endif
///@todo limit cache size
_pathMap[path] = icon._id;
_pathMap[path] = icon;
return icon;
} else
@ -210,7 +268,7 @@ const Icon& IconCache::extract(LPCTSTR path, int idx)
if ((int)ExtractIconEx(path, idx, NULL, &hIcon, 1) > 0) {
const Icon& icon = add(hIcon, IT_CACHED);
_pathIdxMap[key] = icon._id;
_pathIdxMap[key] = icon;
return icon;
} else
@ -242,16 +300,18 @@ const Icon& IconCache::add(HICON hIcon, ICON_TYPE type)
return _icons[id] = Icon(type, id, hIcon);
}
const Icon& IconCache::add(int sys_idx/*, ICON_TYPE type=IT_SYSCACHE*/)
{
int id = ++s_next_id;
return _icons[id] = SysCacheIcon(id, sys_idx);
}
const Icon& IconCache::get_icon(int id)
{
return _icons[id];
}
HBITMAP IconCache::get_icon_bitmap(int id, HBRUSH hbrBkgnd, HDC hdc)
{
return create_bitmap_from_icon(_icons[id]._hIcon, hbrBkgnd, hdc);
}
void IconCache::free_icon(int icon_id)
{
IconMap::iterator found = _icons.find(icon_id);
@ -259,30 +319,12 @@ void IconCache::free_icon(int icon_id)
if (found != _icons.end()) {
Icon& icon = found->second;
if (icon._itype == IT_DYNAMIC) {
DestroyIcon(icon._hIcon);
if (icon.destroy())
_icons.erase(found);
}
}
}
HBITMAP create_bitmap_from_icon(HICON hIcon, HBRUSH hbrush_bkgnd, HDC hdc_wnd)
{
HBITMAP hbmp = CreateCompatibleBitmap(hdc_wnd, 16, 16);
MemCanvas canvas;
BitmapSelection sel(canvas, hbmp);
RECT rect = {0, 0, 16, 16};
FillRect(canvas, &rect, hbrush_bkgnd);
DrawIconEx(canvas, 0, 0, hIcon, 16, 16, 0, hbrush_bkgnd, DI_NORMAL);
return hbmp;
}
ResString::ResString(UINT nid)
{
TCHAR buffer[BUFFER_LEN];
@ -295,17 +337,17 @@ ResString::ResString(UINT nid)
ResIcon::ResIcon(UINT nid)
{
_hIcon = LoadIcon(g_Globals._hInstance, MAKEINTRESOURCE(nid));
_hicon = LoadIcon(g_Globals._hInstance, MAKEINTRESOURCE(nid));
}
SmallIcon::SmallIcon(UINT nid)
{
_hIcon = (HICON)LoadImage(g_Globals._hInstance, MAKEINTRESOURCE(nid), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
_hicon = (HICON)LoadImage(g_Globals._hInstance, MAKEINTRESOURCE(nid), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
}
ResIconEx::ResIconEx(UINT nid, int w, int h)
{
_hIcon = (HICON)LoadImage(g_Globals._hInstance, MAKEINTRESOURCE(nid), IMAGE_ICON, w, h, LR_SHARED);
_hicon = (HICON)LoadImage(g_Globals._hInstance, MAKEINTRESOURCE(nid), IMAGE_ICON, w, h, LR_SHARED);
}

View file

@ -44,7 +44,7 @@ enum ICON_TYPE {
IT_STATIC,
IT_CACHED,
IT_DYNAMIC,
IT_SYSCACHE ///@todo
IT_SYSCACHE
};
enum ICON_ID {
@ -73,16 +73,35 @@ enum ICON_ID {
};
struct Icon {
ICON_ID _id;
ICON_TYPE _itype;
HICON _hIcon;
Icon();
Icon(ICON_ID id, UINT nid);
Icon(ICON_TYPE itype, int id, HICON hIcon);
Icon(ICON_TYPE itype, int id, int sys_idx);
operator ICON_ID() const {return _id;}
void draw(HDC hdc, int x, int y, int cx, int cy, COLORREF bk_color, HBRUSH bk_brush) const;
HBITMAP create_bitmap(COLORREF bk_color, HBRUSH hbrBkgnd, HDC hdc_wnd) const;
int get_sysiml_idx() const {return _itype==IT_SYSCACHE? _sys_idx: -1;}
bool destroy() {if (_itype == IT_DYNAMIC) {DestroyIcon(_hicon); return true;} else return false;}
protected:
ICON_ID _id;
ICON_TYPE _itype;
HICON _hicon;
int _sys_idx;
};
struct SysCacheIcon : public Icon {
SysCacheIcon(int id, int sys_idx)
: Icon(IT_SYSCACHE, id, sys_idx) {}
};
struct IconCache {
IconCache() : _himlSys(0) {}
void init();
const Icon& extract(const String& path);
@ -90,9 +109,10 @@ struct IconCache {
const Icon& extract(IExtractIcon* pExtract, LPCTSTR path, int idx);
const Icon& add(HICON hIcon, ICON_TYPE type=IT_DYNAMIC);
const Icon& add(int sys_idx/*, ICON_TYPE type=IT_SYSCACHE*/);
const Icon& get_icon(int icon_id);
HBITMAP get_icon_bitmap(int icon_id, HBRUSH hbrBkgnd, HDC hdc);
HIMAGELIST get_sys_imagelist() const {return _himlSys;}
void free_icon(int icon_id);
@ -108,6 +128,8 @@ protected:
typedef pair<String, int> CachePair;
typedef map<CachePair, ICON_ID> PathIdxMap;
PathIdxMap _pathIdxMap;
HIMAGELIST _himlSys;
};
@ -151,10 +173,10 @@ struct ResIcon
{
ResIcon(UINT nid);
operator HICON() const {return _hIcon;}
operator HICON() const {return _hicon;}
protected:
HICON _hIcon;
HICON _hicon;
};
/// convenient loading of small (16x16) icon resources
@ -162,10 +184,10 @@ struct SmallIcon
{
SmallIcon(UINT nid);
operator HICON() const {return _hIcon;}
operator HICON() const {return _hicon;}
protected:
HICON _hIcon;
HICON _hicon;
};
/// convenient loading of icon resources with specified sizes
@ -173,10 +195,10 @@ struct ResIconEx
{
ResIconEx(UINT nid, int w, int h);
operator HICON() const {return _hIcon;}
operator HICON() const {return _hicon;}
protected:
HICON _hIcon;
HICON _hicon;
};
/// set big and small icons out of the resources for a window

View file

@ -315,7 +315,7 @@ void Entry::extract_icon()
ICON_ID icon_id = ICID_NONE;
if (get_path(path))
icon_id = g_Globals._icon_cache.extract(path)._id;
icon_id = g_Globals._icon_cache.extract(path);
if (icon_id == ICID_NONE) {
IExtractIcon* pExtract;
@ -325,12 +325,12 @@ void Entry::extract_icon()
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;
icon_id = g_Globals._icon_cache.extract(pExtract, path, idx);
else {
if (idx == -1)
idx = 0; // special case for some control panel applications ("System")
icon_id = g_Globals._icon_cache.extract(path, idx)._id;
icon_id = g_Globals._icon_cache.extract(path, idx);
}
/* using create_absolute_pidl() [see below] results in more correct icons for some control panel applets ("NVidia").
@ -363,8 +363,13 @@ void Entry::extract_icon()
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 ?
HIMAGELIST himlSys = (HIMAGELIST) SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX|SHGFI_PIDL|SHGFI_SMALLICON);
if (himlSys)
icon_id = g_Globals._icon_cache.add(sfi.iIcon);
/*
if (SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(sfi), SHGFI_PIDL|SHGFI_ICON|SHGFI_SMALLICON))
icon_id = g_Globals._icon_cache.add(sfi.hIcon)._id;
*/
}
}

View file

@ -502,7 +502,7 @@ void Pane::draw_item(LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol)
cx = IMAGE_WIDTH;
if (entry->_icon_id > ICID_NONE)
DrawIconEx(dis->hDC, img_pos, dis->rcItem.top, g_Globals._icon_cache.get_icon(entry->_icon_id)._hIcon, cx, GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
g_Globals._icon_cache.get_icon(entry->_icon_id).draw(dis->hDC, img_pos, dis->rcItem.top, cx, GetSystemMetrics(SM_CYSMICON), bkcolor, 0);
else
ImageList_DrawEx(_himl, img, dis->hDC,
img_pos, dis->rcItem.top, cx,

View file

@ -113,6 +113,9 @@ void QuickLaunchBar::AddShortcuts()
ShellFolder desktop_folder;
WindowCanvas canvas(_hwnd);
COLORREF bk_color = GetSysColor(COLOR_BTNFACE);
HBRUSH bk_brush = GetSysColorBrush(COLOR_BTNFACE);
TBBUTTON btn = {0, 0, TBSTATE_ENABLED, BTNS_BUTTON|BTNS_NOPREFIX, {0, 0}, 0, 0};
for(Entry*entry=_dir->_down; entry; entry=entry->_next) {
@ -122,7 +125,7 @@ void QuickLaunchBar::AddShortcuts()
// hide subfolders
if (!(entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
HBITMAP hbmp = g_Globals._icon_cache.get_icon_bitmap(entry->_icon_id, GetSysColorBrush(COLOR_BTNFACE), canvas);
HBITMAP hbmp = g_Globals._icon_cache.get_icon(entry->_icon_id).create_bitmap(bk_color, bk_brush, canvas);
TBADDBITMAP ab = {0, (UINT_PTR)hbmp};
int bmp_idx = SendMessage(_hwnd, TB_ADDBITMAP, 1, (LPARAM)&ab);

View file

@ -1117,21 +1117,22 @@ void DrawStartMenuButton(HDC hdc, const RECT& rect, LPCTSTR title, HICON hIcon,
++textRect.right; ++textRect.bottom;
}
int bk_color = COLOR_BTNFACE;
int text_color = COLOR_BTNTEXT;
int bk_color_idx = COLOR_BTNFACE;
int text_color_idx = COLOR_BTNTEXT;
if (has_focus) {
bk_color = COLOR_HIGHLIGHT;
text_color = COLOR_HIGHLIGHTTEXT;
bk_color_idx = COLOR_HIGHLIGHT;
text_color_idx = COLOR_HIGHLIGHTTEXT;
}
HBRUSH bk_brush = GetSysColorBrush(bk_color);
COLORREF bk_color = GetSysColor(bk_color_idx);
HBRUSH bk_brush = GetSysColorBrush(bk_color_idx);
if (title)
FillRect(hdc, &rect, bk_brush);
if (btn._icon_id > ICID_NONE)
DrawIconEx(hdc, iconPos.x, iconPos.y, g_Globals._icon_cache.get_icon(btn._icon_id)._hIcon, 16, 16, 0, bk_brush, DI_NORMAL);
g_Globals._icon_cache.get_icon(btn._icon_id).draw(hdc, iconPos.x, iconPos.y, 16, 16, bk_color, bk_brush);
// draw submenu arrow at the right
if (btn._hasSubmenu) {
@ -1149,7 +1150,7 @@ void DrawStartMenuButton(HDC hdc, const RECT& rect, LPCTSTR title, HICON hIcon,
if (!btn._enabled) // dis->itemState & (ODS_DISABLED|ODS_GRAYED)
DrawGrayText(hdc, &textRect, title, DT_SINGLELINE|DT_NOPREFIX|DT_VCENTER);
else {
TextColor lcColor(hdc, GetSysColor(text_color));
TextColor lcColor(hdc, GetSysColor(text_color_idx));
DrawText(hdc, title, -1, &textRect, DT_SINGLELINE|DT_NOPREFIX|DT_VCENTER);
}
}