[.net] [VB] Returning 16x16 icon for a file as a Bitmap
I am developing a sort of Z80 IDE - screenshot.
Currently, those icons in the project explorer to the right are hard coded (if extension is .inc, use this icon, if extension is .z80, use that icon...)
Ideally, though, I'd get the Windows icon for the files. I'd need to get them in the form of an Image or Bitmap, based solely on the file extension. How would one go about doing this?
SHGetFileInfo will get the shell icon associated with a file, then perhaps use DrawIconEx for displaying it.
I need to get it as an image so I can add it to the image list control - so maybe if I create a new bitmap and draw onto that? I shall have a fiddle. Thanks!
So, I have this function:
...which works fine, but makes the alpha in XP icons a horrible strong black:
Any ideas?
Module mdlIcons Private Declare Function ExtractIconEx Lib "shell32.dll" Alias "ExtractIconExA" (ByVal lpszFile As String, ByVal nIconIndex As Int32, ByRef phiconLarge As Int32, ByRef phiconSmall As Int32, ByVal nIcons As Int32) As Int32 Private Declare Function DestroyIcon Lib "user32.dll" (ByVal hIcon As Int32) As Int32 Function getIconFromFilename(ByVal filename As String, ByVal largeIcon As Boolean) As Bitmap ' Grab the extension: Dim getExtension() As String = filename.Split(".") ' Look up the file type: Dim searchKey As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey("." & getExtension(UBound(getExtension)), False) ' Was anything found? If searchKey Is Nothing Then Return Nothing ' Go through until you hit the end: Dim getDefaultIcon As Microsoft.Win32.RegistryKey Do getDefaultIcon = searchKey.OpenSubKey("DefaultIcon", False) If Not (getDefaultIcon Is Nothing) Then Exit Do searchKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(searchKey.GetValue("")) If searchKey Is Nothing Then Return Nothing Loop ' Get the details: Dim fileDescription As String = searchKey.GetValue("") Dim iconPath As String = getDefaultIcon.GetValue("") ' Close the registry keys: getDefaultIcon.Close() searchKey.Close() ' Now we have that data, we need to convert a "xxxx,0" path into a "xxxx" and a "0" Dim getPlainIconDetails() As String = iconPath.Replace("""", "").Split(",") Dim iconIndex As Integer = 0 Dim plainIconName As String = getPlainIconDetails(0) For i As Integer = 1 To UBound(getPlainIconDetails) - 1 plainIconName &= "," & getPlainIconDetails(i) Next If iconPath.Replace("""", "").ToUpper.EndsWith(".ICO") Then If UBound(getPlainIconDetails) <> 0 Then plainIconName &= getPlainIconDetails(UBound(getPlainIconDetails)) Else iconIndex = Val(getPlainIconDetails(UBound(getPlainIconDetails))) End If ' Now we have all that info, let's grab the icon: Dim iconLarge As Int32 Dim iconSmall As Int32 If (ExtractIconEx(plainIconName, iconIndex, iconLarge, iconSmall, 1) > 0) Then Dim iconPtr As IntPtr If largeIcon = True Then iconPtr = New IntPtr(iconLarge) Else iconPtr = New IntPtr(iconSmall) End If Dim iconRes As Icon = Icon.FromHandle(iconPtr) Dim returnBitmap As Bitmap = iconRes.ToBitmap iconRes.Dispose() If iconLarge <> 0 Then DestroyIcon(iconLarge) If iconSmall <> 0 Then DestroyIcon(iconSmall) Return returnBitmap Else Return Nothing End If End FunctionEnd Module
...which works fine, but makes the alpha in XP icons a horrible strong black:
Any ideas?
I think this does what you want.
I haven't tested that code, but I had a C# code snippet that did just that, so I know it's possible and works well.
Edit: just found the C# snippet, in case anyone's interested:
[Edited by - itachi on September 13, 2005 10:01:51 AM]
I haven't tested that code, but I had a C# code snippet that did just that, so I know it's possible and works well.
Edit: just found the C# snippet, in case anyone's interested:
using System;using System.Drawing;using System.Drawing.Imaging;using System.Runtime.InteropServices; public sealed class Tools { public struct ICONINFO { public bool fIcon; public int xHotspot; public int yHotspot; public IntPtr hbmMask; public IntPtr hbmColor; } [DllImport("gdi32.dll", SetLastError = true)] static public extern bool DeleteObject(IntPtr hObject); [DllImport("user32.dll")] public static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO piconinfo); public static Bitmap IconToAlphaBitmap(Icon ico) { if (ico == null) return null; ICONINFO ii = new ICONINFO(); GetIconInfo(ico.Handle, out ii); Bitmap bmp = Bitmap.FromHbitmap(ii.hbmColor); DeleteObject(ii.hbmColor); DeleteObject(ii.hbmMask); if (Bitmap.GetPixelFormatSize(bmp.PixelFormat) < 32) { bmp.Dispose(); return ico.ToBitmap(); } Rectangle bmBounds = new Rectangle(0, 0, bmp.Width, bmp.Height); BitmapData bmData = bmp.LockBits(bmBounds, ImageLockMode.ReadOnly, bmp.PixelFormat); Bitmap dstBitmap = new Bitmap(bmData.Width, bmData.Height, bmData.Stride, PixelFormat.Format32bppArgb, bmData.Scan0); bool hasAlpha = false; for (int y=0; y <= bmData.Height-1; y++) { for (int x=0; x <= bmData.Width-1; x++) { Color PixelColor = Color.FromArgb(Marshal.ReadInt32(bmData.Scan0, (bmData.Stride * y) + (4 * x))); if (PixelColor.A > 0 & PixelColor.A < 255) { hasAlpha = true; break; } } if (hasAlpha) break; } bmp.UnlockBits(bmData); if (hasAlpha) return new Bitmap(dstBitmap); dstBitmap.Dispose(); return new Bitmap(ico.ToBitmap()); }}
[Edited by - itachi on September 13, 2005 10:01:51 AM]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement