HICONs vergleichen
-
Geht das denn nicht irgendwie schneller? Na ja werd ich wohl so mache müssen..
Zumal ich da erstmal das HICON zu einer HBITMAP machen muss
-
GetIconInfo + GetObject + CreateCompatibleDC + GetDIBits + DeleteDC
-
Du willst aber jetzt nicht deine komplette Imagelist durchsuchen, ob ein bestimmtes Icon schon vorhanden ist, oder?
Wie es gehen kann, habe ich ja schon geschrieben, 2 Imagelists erstellen, entweder selber zeichnen oder den Controls per TVM_SETIMAGELIST (Treeview) und LVM_SETIMAGELIST (Listview) das Handle den Controls zukommen lassen und ShGetFileInfo das Flag SHGFI_SYSICONINDEX übergeben - fertig.
-
Die Frage hatte zwar gar nicht darauf abgezielt, aber mir fällt gerade auf, dass ich das wohl tatsächlich genau so gemacht hätte

Ich kann deinem Code leider nicht entnehmen, wie ich prüfen kann, ob ein Icon schon in der ImageList vorhanden ist. Bzw. muss ich das überhaupt? Ich verstehe deinen Ansatz wohl nicht so ganz, vielleicht kannst du das noch mal näher erläutern? (Am besten mit Code - und ich brauche nur SmallIcons, das Makro kannste sparen :D)
-
Jetzt mal ganz schnell zusammengezimmert:
int AddListViewEntry(HWND hwndLV, const TCHAR* pText, int groupid = -1, int iconindex = -1) { LVITEM lvi = {0}; int pos = SendMessage(hwndLV,LVM_GETITEMCOUNT,0,0); lvi.iItem = pos; lvi.mask = LVIF_TEXT; lvi.iSubItem = 0; if(groupid!=-1) { lvi.mask |= LVIF_GROUPID; lvi.iGroupId = groupid; } if(iconindex!=-1) { lvi.mask |= LVIF_IMAGE; lvi.iImage = iconindex; } lvi.pszText = const_cast<TCHAR*>(pText); return ListView_InsertItem(hwndLV, &lvi); } int SetListViewEntry(HWND hwndLV, const TCHAR* pText, int pos, int sub) { LVITEM lvi = {0}; lvi.iItem = pos; lvi.mask = LVIF_TEXT; lvi.iSubItem = sub; lvi.pszText = const_cast<TCHAR*>(pText); return ListView_SetItem(hwndLV,&lvi); } HIMAGELIST CreateImageList(bool large) { HIMAGELIST imageList; SHFILEINFO sfi; imageList = reinterpret_cast<HIMAGELIST>(SHGetFileInfo(TEXT("C:\\"), 0, &sfi, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX | (large ? 0 : SHGFI_SMALLICON))); return imageList; } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { static HIMAGELIST imgSmall = CreateImageList(false); switch (msg) { case WM_CREATE: { RECT cl; GetClientRect(hwnd, &cl); HWND lv = CreateWindow(WC_LISTVIEW ,TEXT(""), WS_VISIBLE | WS_CHILD | WS_BORDER | LBS_NOINTEGRALHEIGHT, 0,0,cl.right,cl.bottom,hwnd, (HMENU)30000,reinterpret_cast<LPCREATESTRUCT>(lParam)->hInstance,0); SendMessage(lv,LVM_SETVIEW, LV_VIEW_DETAILS, 0); SendMessage(lv,LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)imgSmall); LVCOLUMN lvc; lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT; lvc.fmt = LVCFMT_LEFT; lvc.cx = 100; SendMessage(lv,LVM_SETITEMCOUNT,2,0); lvc.pszText = TEXT("Name"); ListView_InsertColumn(lv, 0, &lvc); lvc.pszText = TEXT("Zusatz"); ListView_InsertColumn(lv, 1, &lvc); ////////////////////////////////////////////////////////////////////////// // Das hier kann dann in eine Funktion gepackt werden const TCHAR* pFile = TEXT("c:\\irgendeine Datei.exe"); SHFILEINFO sfi; int iconindex=-1; if(SHGetFileInfo(pFile, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX | SHGFI_SMALLICON)) { iconindex=sfi.iIcon; } int pos = AddListViewEntry(lv, pFile, -1, iconindex); SetListViewEntry(lv, TEXT("Zusatzinfo 1"), pos, 1); ////////////////////////////////////////////////////////////////////////// break; } } ... }Aber wie auch scon geschrieben, das Laden der Icons von exe-Dateien dauert etwas. Wenn der Sysetm32-Ordner geöffnet wird, möchte der Benutzer normalerweise nicht erst zig Sekunden warten. Daher wäre es am Besten, die Icons erst dann zu laden, wenn sie auch wirklich angezeigt werden müssen (erfordert evtl LVS_OWNERDATA).
-
Super, danke! (Ich hatte das mit dem ICONINDEX einfach nicht gerafft.)
yahendrik schrieb:
Wenn der Sysetm32-Ordner geöffnet wird
Wird er nicht.

-
Zwei Fragen hätte ich noch:
1. Ich durchsuche die Platte ja mit FindFirstFile()/FindNextFile(). Muss ich dann wirklich jedes mal noch SHGetFileInfo aufrufen oder geht das eleganter?
2. SHGetFileInfo mit SHGFI_SYSICONINDEX funktioniert bei Festplatten zwar wunderbar, aber für Ordner/Dateien bekomme ich als Index immer nur 1 zurück, und das ist irgendein komisches weißes Blatt. Kannst du so schon vermuten was ich falsch mache, oder brauchst du mehr Code? SHGetFileInfo wird so aufgerufen:
SHGetFileInfo(s.c_str(), 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX | SHGFI_SMALLICON);Bzw. das erste Mal so:
char buf[0x100]; GetWindowsDirectory(buf, sizeof(buf)); SHFILEINFO sfi; m_img_list = (HIMAGELIST)SHGetFileInfo(buf, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX | SHGFI_SMALLICON); // man möge mir den C Cast verzeihen TreeView_SetImageList(m_hwnd, m_img_list, TVSIL_NORMAL);
-
Ich kann das gerade nicht überprüfen, aber zwei Anmerkungen:
Zu 1: Du kannst natürlich von der Dateiendung (sofern es sich um keine Datei mit eigenem Icon handelt) auch auf den Index schließen, falls du die Kombination schon irgendwo gespeichert hast (vielleicht in einer std::map). Ganz nebenbei kannst du dir auch noch die Beschreibung (SHGFI_TYPENAME) speichern, die als Überschrift in einer Gruppenansicht der Listview ganz nützlich ist.Ja und zu 2 weiß ichs auch nicht so recht... Irgendwas machst du falsch.
Falls es kein Fehler beim Einfügen hier ist: Du erstellst eine Img-List mit kleinen Icons.TreeView_SetImageList(m_hwnd, m_img_list, TVSIL_NORMAL);Der letzte Parameter sollte TVSIL_SMALL sein.
Außerdem, evtl. etwas abwegig: Du hast eine Funktion, die als Parameter den Dateipfad erwartet, zum Testen übergibt du bspw.TEXT("d:\\"), aber Funktionen wie GetWindowsDirectory/GetCurrentDirectory fügen den abschließenden Backslash nicht hinzu.
-
yahendrik schrieb:
Irgendwas machst du falsch.

yahendrik schrieb:
TVSIL_SMALL
Gibt's gar nicht.
http://msdn.microsoft.com/en-us/library/bb760056(v=vs.85).aspxyahendrik schrieb:
TEXT("d:\\")Funktioniert auch nicht. Komische Sache. Dabei brauche ich eigentlich auch nur die Icons der Festplatten und Ordner, Dateiicons sind egal. Vielleicht muss ich das dann doch mit einem Vergleich machen

-
schon gut...
Edit2: Das Problem ist, dass ich gerade nicht richtig gelesen habe, ich dachte du wärst noch bei der Listview. Bei Treeviews kann ich dir auch wenig helfen, ich habe meine Eigene, die ich ausschließlich nutze.