Imageliste mit System
Eine Imageliste ist eine Ansammlung von Bildobjekten gleicher Größe und Farbauflösung, die anhand ihres Index innerhalb der Liste referenziert werden. Die einzelnen Bildobjekte können auf einfache und vielfältige Weise gezeichnet werden. Listenansicht und Baumansicht nutzen die Imageliste zur Darstellung von Symbolen, jeder Eintrag in den beiden Ansichten kann als Eigenschaft einen Index des darzustellenden Symbols innerhalb einer Imageliste enthalten. Die zu verwendende Imageliste wird den beiden Ansichten mit einer Funktion zugewiesen.
Die Systemimageliste ist eine von der Shell erzeugte und gepflegte Imageliste, genaugenommen sind es sogar mehrere. Bis einschließlich Windows 2000 verwendet die Shell zwei Imagelisten (16×16 und 32×32), mit Windows XP kam eine dritte (48×48) hinzu. Unter Windows 9x/ME wird für alle Prozesse eine gemeinsame Systemimageliste verwendet, jede Manipulation hat auch Auswirkungen auf alle anderen Prozesse. Unter Windows NT/2000/XP erhält jeder Prozess eine eigene Systemimageliste, Änderungen an dieser betreffen dann nur noch die eigene und nicht die der anderen Prozesse.
Der Zugriff auf die Systemimageliste erfolgt über die Funktion SHGetFileInfo. Der Rückgabewert von SHGetFileInfo ist ein Handle auf eine Imageliste, entweder auf die kleine (16×16) oder auf die große (32×32). Die extragroße Imageliste (48×48) unter Windows XP kann durch SHGetFileInfo nicht ermittelt werden, hierfür muss die Funktion SHGetImageList verwendet werden. Zur einfachen Handhabung habe ich mir eine Funktion Lwl_ShlGetSystemImageList geschrieben, die alle nötigen Aufrufe kapselt und abwärtskompatibel bis Windows 95 ist. Die Parameter sind SHIL_LARGE (32×32), SHIL_SMALL (16×16) und SHIL_EXTRALARGE (48×48), alle 3 Konstanten sind in der Headerdatei ShellAPI.h definiert.
HIMAGELIST Lwl_ShlGetSystemImageList(int iImageList) { // 16x16 und 32x32 auf konventionelle Art if (SHIL_SMALL == iImageList || SHIL_LARGE == iImageList) { // Flags zusammenstellen SHFILEINFO sfi; DWORD dwFlags = SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES; dwFlags |= (SHIL_SMALL == iImageList ? SHGFI_SMALLICON : SHGFI_LARGEICON); // Imageliste abrufen return (HIMAGELIST) SHGetFileInfo(_T("123.txt"), 0, &sfi, sizeof(SHFILEINFO), dwFlags); } // 48x48-Imageliste abrufen HIMAGELIST hImageList = NULL; if (S_OK != _SHGetImageList(iImageList, IID_IImageList, (void**) &hImageList)) return NULL; // Ans kloar return hImageList; }
Die Funktion _SHGetImageList importiert SHGetImageList dynamisch und ruft diese bei Verfügbarkeit auf. Somit ist die Lauffähigkeit auch unter älteren Windows-Versionen sichergestellt.
typedef HRESULT (STDMETHODCALLTYPE *SHGETIMAGELIST)(int, REFIID, void**); STDAPI _SHGetImageList(int iImageList, REFIID riid, void** ppv) { // Alles wird gut HRESULT hResult = S_OK; // Dll laden HINSTANCE hInstShell32 = LoadLibrary(_T("Shell32.dll")); if (NULL == hInstShell32) return HRESULT_FROM_WIN32(GetLastError()); // Funktion anhand des Namens importieren SHGETIMAGELIST pfn = (SHGETIMAGELIST) GetProcAddress(hInstShell32, "SHGetImageList"); // Funktion aufrufen if (NULL != pfn) { hResult = (pfn)(iImageList, riid, ppv); } // Funktion ist nicht vorhanden else { hResult = HRESULT_FROM_WIN32(GetLastError()); } // Dll freigeben FreeLibrary(hInstShell32); // Ans kloar return hResult; }
Lwl_ShlGetSystemImageList gibt das Handle auf die gewünschte Imageliste zurück. Wenn diese noch nicht existiert, dann werden unter Windows NT/2000/XP alle zwei (bzw. ab XP drei) Imagelisten erstellt und mit folgenden Symbolen gefüllt:
- Freigabesymbol (Overlay)
- Verknüpfungssymbol (Overlay)
- Offlinesymbol (Overlay)
- Unbekannter Dateityp
- Textdatei
Unter Windows 9x/ME ist mit sehr großer Wahrscheinlichkeit der Explorer die erste Anwendung, welche die Systemimageliste initialisiert. Alle anderen nachfolgenden Prozesse bekommen dann einen Verweis auf die bereits gut gefüllte Imageliste zurück.
Jeder nachfolgende Aufruf von SHGetFileInfo zur Ermittlung von Dateisymbolen fügt das entsprechende Symbol dann der Systemimageliste hinzu, sofern es noch nicht in dieser enthalten ist. Alle zwei (oder drei) Imagelisten werden synchron gefüllt, so dass ein Index für ein Symbol in der 16×16-Liste gleich dem Index in der 32×32-Liste ist.
Sehr gut beschrieben! Das wird hier noch eine richtige Referenz-Sanmmlung. Ich freu mich schon drauf wenn Sven eeeeeeeeeeendlich .NET macht. Das wird dann cool 🙂
Danke! Mit .NET habe ich schon ein wenig gespielt (zwecks AddIns für den SC11), aber mehr passiert damit vorerst auch nicht. 😉