Feedback

C# - SystemIconsImageListWrapper

Veröffentlicht von am 2/14/2011
(1 Bewertungen)
Diese Klasse ist ein Wrapper für eine ImageList, mit der es möglich ist, Icons für beliebig auf dem System registrierte Dateierweiterungen abzurufen.

Die Klasse cached intern jedes Icon, sodass pro Extension nur einmal das Icon geladen werden muss.

Anwendungsbeispiel:
In einer Form wird der Wrapper als Klaassenvariable instanziiert:
this.SIILW = new SystemIconsImageListWrapper(this.imageList1, 2);


imageList1 ist dabei eine schon vorhandene ImageList, die an Index 2 ein Icon enthält, dass als Default Icon fungiert, sofern für eine Extension kein Icon gefunden wird.

Hier wird dann z. B. einer TreeNode ein Icon anhand einer File Extension zugewiesen:
TreeNode TNToAdd = new TreeNode("Doc Datei");
TNToAdd.ImageIndex = this.SIILW.GetSIImageListIndexForFileExtension(".doc");
this.treeView1.Nodes.Add(TNToAdd);

(Der zur TreeNode zugehörigen TreeView ist die vorhandene und im Wrapper referenziert imageList1 zugeordnet.)
Der int GetSIImageListIndexForFileExtension(string Extension) lad das Icon in die referenzierte ImageList, sofern nicht vorhanden, und gibt den Index zurück.
using System;
using System.Collections.Generic;
using Microsoft.Win32;
using System.Windows.Forms;
using System.Drawing;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Drawing.Drawing2D;

public sealed class SystemIconsImageListWrapper : Object
    {
        public SystemIconsImageListWrapper()
        {
            this.SIImageList = new ImageList();
            this.ExtensionSIImageListIndexZuordnung = new Dictionary<string, int>();
        }

        public SystemIconsImageListWrapper(ImageList IL, int DefaultIconIndex)
        {
            this.SIImageList = IL;
            this.ExtensionSIImageListIndexZuordnung = new Dictionary<string, int>();
            this.DefaultIconIndex = DefaultIconIndex;
        }

        public ImageList SIImageList { get; set; }
        private Dictionary<string, int> ExtensionSIImageListIndexZuordnung;
        private int DefaultIconIndex = 0;

        public int GetSIImageListIndexForFileExtension(string Extension)
        {
            try
            {
                int RValue = 0;

                if (!Extension.StartsWith("."))
                    Extension = "." + Extension;

                if (this.ExtensionSIImageListIndexZuordnung.ContainsKey(Extension))
                    this.ExtensionSIImageListIndexZuordnung.TryGetValue(Extension, out RValue);
                else //noch nicht vorhanden -> laden
                {
                    this.SIImageList.Images.Add(this.GetIconForFileExtension(Extension));

                    this.ExtensionSIImageListIndexZuordnung.Add(Extension, this.SIImageList.Images.Count - 1);

                    this.ExtensionSIImageListIndexZuordnung.TryGetValue(Extension, out RValue);
                }

                return RValue;
            }
            catch (Exception ex) //Bei Fehler einfach DefaultIconIndex zurückgeben
            {
                ex.ToString(); //Suppress Visual Studio unused variable warning
                return this.DefaultIconIndex;
            }
        }

        private Icon GetIconForFileExtension(string Extension)
        {
            if (!Extension.StartsWith("."))
                Extension = "." + Extension;

            KeyValuePair<string, int> QryRS = this.GetIconPathForExtension(Extension);

            if (!string.IsNullOrEmpty(QryRS.Key))
                return this.GetIconFromDLL(QryRS.Key, QryRS.Value);
            else //Icon nicht gefunden oder Fehler -> Default Icon verwenden
                return this.ImageToIcon(this.SIImageList.Images[this.DefaultIconIndex]);
        }

        private KeyValuePair<string, int> GetIconPathForExtension(string Extension)
        {
            if (!Extension.StartsWith("."))
                Extension = "." + Extension;

            KeyValuePair<string, int> RValue = new KeyValuePair<string, int>(string.Empty, 0);

            try
            {
                RegistryKey ClassRootKey = Registry.ClassesRoot;
                string FileExtSubKeyName = ClassRootKey.OpenSubKey(Extension).GetValue("").ToString(); //Default Value

                string IconPathRaw = ClassRootKey.OpenSubKey(FileExtSubKeyName).OpenSubKey("DefaultIcon").GetValue("").ToString(); //Default Value

                RValue = new KeyValuePair<string, int>(IconPathRaw.Split(',')[0], int.Parse(IconPathRaw.Split(',')[1]));
            }
            catch (Exception ex)
            {
                ex.ToString(); //Suppress Visual Studio unused variable warning
            }

            return RValue;
        }

        private Icon GetIconFromDLL(string PathToDLL, int IconIndex)
        {
            IntPtr EigenesProzessHandle = Process.GetCurrentProcess().Handle;

            IntPtr DLLIconPointer = ExtractIcon(EigenesProzessHandle, PathToDLL, IconIndex);

            return Icon.FromHandle(DLLIconPointer);
        }

        [DllImport("shell32.dll")]
        private static extern IntPtr ExtractIcon(IntPtr hInst, string lpszExeFileName, int nIconIndex);

        private Icon ImageToIcon(Image img)
        {
            int size = 24;
            using (Bitmap square = new Bitmap(size, size))
            {
                Graphics g = Graphics.FromImage(square);
                int x;
                int y;
                int w;
                int h;
                float r = (float)img.Width / (float)img.Height;
                if (r > 1)
                {
                    w = size;
                    h = (int)((float)size / r);
                    x = 0;
                    y = (size - h) / 2;
                }
                else
                {
                    w = (int)((float)size * r);
                    h = size;
                    y = 0;
                    x = (size - w) / 2;
                }
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.DrawImage(img, x, y, w, h);
                g.Flush();
                return Icon.FromHandle(square.GetHicon());
            }
        }
    }
Abgelegt unter system, icon, file, extension, image, list, imagelist, wraper, c#, csharp.

2 Kommentare zum Snippet

10110010 schrieb am 3/26/2012:
Das ist eine elegante Lösung.
Ich bin auch diesen Weg gegangen, allerding hat diese Ausführung noch einen Haken!
Die Icons, die Versionsbedingt in der Registry angegeben sind, werden hier nicht gefunden.
Dazu gehören z.B. die PDF Icons.

Um auch diese zu erhallten, sollte vorher abgefragt werden ob der Schlüssen DefaultIcon enthalten ist. Ist dies nicht der fall, existiert eigentlich immer ein Schlüssen "CurVer" in der der Verweis auf den Korekten Schlüssel enthalten ist.
Zum anderen ist der Split auf das "," nicht optimal gewählt, da Verzeichnisse auch Kommas enthalten können und so eine Exception verursacht werden würde.
Hier ist es optimaler sich den Index des letzten Kommas geben zu lassen "IconPathRaw.LastIndexOf(",")".

Das hier ist wie gesagt ansonsten eine schöne Lösung.
Thomas Schoch schrieb am 3/26/2012:
Es kann auch sein, dass IconPathRaw kein "," enthält. In diesem Fall muss vermutlich 0 als Index für das Icon verwendet werden. Dies passiert z.B. auf einem Windows 7 Rechner für die Extension ".zip", falls kein WinZip oder so installiert ist.

Ansonsten klappt das wunderbar.
 

Logge dich ein, um hier zu kommentieren!