2012-11-13 37 views
3

我目前正在研究一個小型庫,使您可以從文件和文件夾中獲取圖標。現在,我不在乎它是否只適用於win8 +(因爲這是我將要使用它的地方),但是,我已經遇到了一個關於透明度的小問題。如果你看看下面的圖片:在C#中獲取文件和文件夾的透明shell圖標

Differences

一個我生成(從我的庫)是向左,Windows資源管理器右邊。
現在,您可能會看到,首先在我生成的右上角有兩條黑線,其次是背景顏色有所不同。所以我想知道的是這個;有沒有辦法獲得完全相同的圖像使用的Windows資源管理器,或者我只是做錯了?

我的代碼(除了結構體/ extern等的簡稱)波紋管,整個代碼here

public static class Icon 
{ 
    public static Image GetIcon(string fileName, int size) 
    { 
     IShellItem shellItem; 
     Shell32.SHCreateItemFromParsingName(fileName, IntPtr.Zero, Shell32.IShellItem_GUID, out shellItem); 

     IntPtr hbitmap; 
     ((IShellItemImageFactory)shellItem).GetImage(new SIZE(size, size), 0x0, out hbitmap); 

     // get the info about the HBITMAP inside the IPictureDisp 
     DIBSECTION dibsection = new DIBSECTION(); 
     Gdi32.GetObjectDIBSection(hbitmap, Marshal.SizeOf(dibsection), ref dibsection); 
     int width = dibsection.dsBm.bmWidth; 
     int height = dibsection.dsBm.bmHeight; 

     // zero out the RGB values for all pixels with A == 0 
     // (AlphaBlend expects them to all be zero) 
     for (int i = 0; i < dibsection.dsBmih.biWidth * dibsection.dsBmih.biHeight; i++) 
     { 
      IntPtr ptr = dibsection.dsBm.bmBits + (i * Marshal.SizeOf(typeof(RGBQUAD))); 
      var rgbquad = (RGBQUAD)Marshal.PtrToStructure(ptr, typeof(RGBQUAD)); 
      if (rgbquad.rgbReserved == 0) 
      { 
       rgbquad.rgbBlue = 0; 
       rgbquad.rgbGreen = 0; 
       rgbquad.rgbRed = 0; 
      } 
      else 
      { 
       ; 
      } 
      Marshal.StructureToPtr(rgbquad, ptr, false); 
     } 

     // create the destination Bitmap object 
     Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); 

     // get the HDCs and select the HBITMAP 
     Graphics graphics = Graphics.FromImage(bitmap); 

     IntPtr hdcDest = graphics.GetHdc(); 
     IntPtr hdcSrc = Gdi32.CreateCompatibleDC(hdcDest); 
     IntPtr hobjOriginal = Gdi32.SelectObject(hdcSrc, hbitmap); 

     // render the bitmap using AlphaBlend 
     BLENDFUNCTION blendfunction = new BLENDFUNCTION(BLENDFUNCTION.AC_SRC_OVER, 0, 0xFF, BLENDFUNCTION.AC_SRC_ALPHA); 
     Gdi32.AlphaBlend(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, width, height, blendfunction); 

     // clean up 
     Gdi32.SelectObject(hdcSrc, hobjOriginal); 
     Gdi32.DeleteDC(hdcSrc); 
     graphics.ReleaseHdc(hdcDest); 
     graphics.Dispose(); 
     Gdi32.DeleteObject(hbitmap); 

     return bitmap; 
    } 
} 

回答

3

看來像素逐個像素複製是解決方案。以下似乎是像素完美相等的探險家之一。

public static Image GetIcon(string fileName, int size) 
    { 
     IShellItem shellItem; 
     Shell32.SHCreateItemFromParsingName(fileName, IntPtr.Zero, Shell32.IShellItem_GUID, out shellItem); 

     IntPtr hbitmap; 
     ((IShellItemImageFactory)shellItem).GetImage(new SIZE(size, size), 0x0, out hbitmap); 

     // get the info about the HBITMAP inside the IPictureDisp 
     DIBSECTION dibsection = new DIBSECTION(); 
     Gdi32.GetObjectDIBSection(hbitmap, Marshal.SizeOf(dibsection), ref dibsection); 
     int width = dibsection.dsBm.bmWidth; 
     int height = dibsection.dsBm.bmHeight; 

     // create the destination Bitmap object 
     Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); 

     for (int x = 0; x < dibsection.dsBmih.biWidth; x++) 
     { 
      for (int y = 0; y < dibsection.dsBmih.biHeight; y++) 
      { 
       int i = y * dibsection.dsBmih.biWidth + x; 
       IntPtr ptr = dibsection.dsBm.bmBits + (i * Marshal.SizeOf(typeof(RGBQUAD))); 
       var rgbquad = (RGBQUAD)Marshal.PtrToStructure(ptr, typeof(RGBQUAD)); 

       if (rgbquad.rgbReserved != 0) 
        bitmap.SetPixel(x, y, Color.FromArgb(rgbquad.rgbReserved, rgbquad.rgbRed, rgbquad.rgbGreen, rgbquad.rgbBlue)); 
      } 
     } 

     Gdi32.DeleteObject(hbitmap); 

     return bitmap; 
    } 
+0

這不太適合我。我查了一下我需要從'gdi32.dll'導入的函數和結構,但是它們似乎並不完全正確。例如,'dibsection.dsBmih.biWidth'總是0.你的'Gdi32'類是什麼? –

+0

Gdi32類是一個簡單的類,包含直接映射到'gdi32.dll'的'internal static extern'方法。 – Alxandr

相關問題