[一分钟学会系列之五]一分钟学会提取文件图标,保存为透明图片(附DEMO程序)

这篇文章介绍一种提取文件或者文件夹的图标的方法,可以保存为背景透明的PNG图标,没有讨厌的黑色背景,嘿嘿。

1. 首先从文件中提取HICON数据,非常简单

    // 调用方负责DestroyIcon HICON
    HICON GetFileIcon(const CString& strFilePath, BOOL bLarge)
    {
        SHFILEINFO SHFI;
        ZeroMemory(&SHFI, sizeof(SHFI));
        DWORD_PTR ret = ::SHGetFileInfo(strFilePath, 0, &SHFI, sizeof(SHFI),
            SHGFI_ICON | (bLarge ? SHGFI_LARGEICON : SHGFI_SMALLICON));

        if (ret != 0)
        {
            return SHFI.hIcon;
        }

        return NULL;
    } 

2. 从HICON中拿出HBITMAP数据,做一些手脚,把它保存成透明的PNG图片

    bool SaveHIcon2PngFile(HICON hIcon, LPCTSTR lpszPicFileName)
    {  
        if (hIcon == NULL)
        {
            return false;
        }

        ICONINFO icInfo = { 0 };    
        if (!::GetIconInfo(hIcon, &icInfo))
        {
            return false;
        }

        BITMAP bitmap;
        GetObject(icInfo.hbmColor, sizeof(BITMAP), &bitmap);

        Gdiplus::Bitmap* pBitmap = NULL;
        Gdiplus::Bitmap* pWrapBitmap = NULL;
        if (bitmap.bmBitsPixel != 32)
        {   
            pBitmap = Gdiplus::Bitmap::FromHICON(hIcon);
        }
        else
        {
            pWrapBitmap = Gdiplus::Bitmap::FromHBITMAP(icInfo.hbmColor, NULL);
            if (!pWrapBitmap)
                return false;

            Gdiplus::BitmapData bitmapData;
            Gdiplus::Rect rcImage(0, 0, pWrapBitmap->GetWidth(), pWrapBitmap->GetHeight());
            pWrapBitmap->LockBits(&rcImage, Gdiplus::ImageLockModeRead, pWrapBitmap->GetPixelFormat(), &bitmapData);
            pBitmap = new Gdiplus::Bitmap(bitmapData.Width, bitmapData.Height, bitmapData.Stride, PixelFormat32bppARGB, (BYTE*)bitmapData.Scan0);
            pWrapBitmap->UnlockBits(&bitmapData);
        }

        CLSID encoderCLSID;
        GetEncoderClsid(_T("image/png"), &encoderCLSID);
        Gdiplus::Status st= pBitmap->Save(lpszPicFileName ,&encoderCLSID, NULL/*&encoderParameters*/);
        if( st != Gdiplus::Ok )
            return false;

        delete pBitmap;
        if (pWrapBitmap)
            delete pWrapBitmap;
        DeleteObject(icInfo.hbmColor);
        DeleteObject(icInfo.hbmMask);  

        return true;
    }


    int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
    {
        UINT  num = 0;          // number of image encoders
        UINT  size = 0;         // size of the image encoder array in bytes

        Gdiplus::ImageCodecInfo* pImageCodecInfo = NULL;

        Gdiplus::GetImageEncodersSize(&num, &size);
        if(size == 0)
            return -1;  // Failure

        pImageCodecInfo = (Gdiplus::ImageCodecInfo*)(malloc(size));
        if(pImageCodecInfo == NULL)
            return -1;  // Failure

        GetImageEncoders(num, size, pImageCodecInfo);

        for(UINT j = 0; j < num; ++j)
        {
            if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
            {
                *pClsid = pImageCodecInfo[j].Clsid;
                free(pImageCodecInfo);
                return j;  // Success
            }    
        }

        free(pImageCodecInfo);
        return -1;  // Failure
    }


3. HICON使用完要记得释放掉

    BOOL SaveFileIcon(const CString& strFilePath, const CString& strImagePath, BOOL bLarge = TRUE)
    {
        BOOL bRet = FALSE;
        HICON hIcon = GetFileIcon(strFilePath, bLarge);
        if (hIcon != NULL)
        {
            bRet = SaveHIcon2PngFile(hIcon, strImagePath);
            ::DestroyIcon(hIcon);
        }

        return bRet;
    }


上面的代码使用了gdiplus,需要包含gdiplus.h,链接gdiplus.lib,并初始化gdiplus环境(GdiplusStartup)。

完整的例子可以去这里下载: http://download.csdn.net/source/3525053

[一分钟学会系列之五]一分钟学会提取文件图标,保存为透明图片(附DEMO程序)_第1张图片


你可能感兴趣的:(image,null,delete,byte)