这篇文章介绍一种提取文件或者文件夹的图标的方法,可以保存为背景透明的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