今天设计CSWComboBox控件发现CImageFactory类接口加载系统ICON资源文件失败,几经周折找到了几种解决方案,其一可以将资源文件类型ICON,改为非系统默认类型(比如MICON,ICON1等等);或者修改代码如下:
Bitmap* CImageFactory::GetSkinItemImage(UINT uiResID, LPCTSTR lpszResType)
{
ImgResource* pImgResource = NULL;
std::map<UINT, ImgResource*>::iterator iter;
iter = m_mapSkinResItems.find(uiResID);
if (iter == m_mapSkinResItems.end())
{
HINSTANCE hInst = AfxGetResourceHandle();
// HINSTANCE hInst = AfxGetInstanceHandle();
// HINSTANCE hInst = AfxFindResourceHandle(MAKEINTRESOURCE(uiResID));
// HINSTANCE hInst = GetModuleHandle(NULL);
HRSRC hResrc = ::FindResource(hInst, MAKEINTRESOURCE(uiResID), lpszResType);
if (hResrc == NULL)
{
TRACE("%d\n", GetLastError());
if (lpszResType == RT_ICON)
{
HICON hIcon = ::LoadIcon(hInst, MAKEINTRESOURCE(uiResID));
if (hIcon)
{
pImgResource = new ImgResource();
pImgResource->pImage = (Gdiplus::Bitmap*)Bitmap::FromHICON(hIcon);
Gdiplus::Status result = pImgResource->pImage->GetLastStatus();
if (result == Gdiplus::Ok)
{
m_mapSkinResItems[uiResID] = pImgResource;
return pImgResource->pImage;
}
}
}
else if (lpszResType == RT_BITMAP)
{
HBITMAP hBitmap = ::LoadBitmap(hInst, MAKEINTRESOURCE(uiResID));
if (hBitmap)
{
pImgResource = new ImgResource();
//pImgResource->pImage = (Gdiplus::Bitmap*)Bitmap::FromHBITMAP(hBitmap, NULL);// 如果hBitmap存在透明度,上面方法就是丢失掉图像中的Alpha信息,具有透明度的像素点将显示黑色
pImgResource->pImage = (Gdiplus::Bitmap*)this->GetSkinItemImage(hBitmap);
Gdiplus::Status result = pImgResource->pImage->GetLastStatus();
if (result == Gdiplus::Ok)
{
m_mapSkinResItems[uiResID] = pImgResource;
return pImgResource->pImage;
}
}
}
return NULL;
}
DWORD dwSize = SizeofResource(hInst, hResrc);
HGLOBAL hGlobal = LoadResource(hInst, hResrc);
if (hGlobal == NULL)
return NULL;
BYTE* lpResrc = (BYTE*)LockResource(hGlobal);
if (lpResrc == NULL)
return NULL;
pImgResource = new ImgResource();
HGLOBAL hAllocMem = GlobalAlloc(GMEM_FIXED, dwSize);
BYTE* pMem = (BYTE*)GlobalLock(hAllocMem);
memcpy(pMem, lpResrc, dwSize);
IStream* pStream = NULL;
CreateStreamOnHGlobal(hAllocMem, FALSE, &pStream);
pImgResource->pImage = (Gdiplus::Bitmap*)Bitmap::FromStream(pStream);
Gdiplus::Status result = pImgResource->pImage->GetLastStatus();
if (result == Gdiplus::Ok)
{
pStream->Release();
GlobalUnlock(hAllocMem);
GlobalFree(hAllocMem);
m_mapSkinResItems[uiResID] = pImgResource;
return pImgResource->pImage;
}
else
{
pStream->Release();
GlobalUnlock(hAllocMem);
GlobalFree(hAllocMem);
if (lpszResType == RT_GROUP_ICON)
{
HICON hIcon = LoadIcon(hInst, MAKEINTRESOURCE(uiResID));
if (hIcon)
{
pImgResource->pImage = (Gdiplus::Bitmap*)Bitmap::FromHICON(hIcon);
Gdiplus::Status result = pImgResource->pImage->GetLastStatus();
if (result == Gdiplus::Ok)
{
pStream->Release();
GlobalUnlock(hAllocMem);
GlobalFree(hAllocMem);
m_mapSkinResItems[uiResID] = pImgResource;
return pImgResource->pImage;
}
}
}
}
delete pImgResource->pImage;
pStream->Release();
GlobalUnlock(hAllocMem);
GlobalFree(hAllocMem);
return NULL;
}
else
{
pImgResource = iter->second;
}
return pImgResource->pImage;
}
新增加接口,通过HBITMAP转换获取Bitmap:
Gdiplus::Bitmap* CImageFactory::GetSkinItemImage(HBITMAP hBitmap)
{
// 如果图像中没有透明度,调用方法如下:
// m_pBkgrBitmap = Gdiplus::Bitmap::FromHBITMAP(hBitmap, NULL),
// 但是如果存在透明度,上面方法就是丢失掉图像中的Alpha信息,具有透明度的像素点将显示黑色,改用如下方法:
BITMAP bmp = { 0 };
if (0 == GetObject(hBitmap, sizeof(BITMAP), (LPVOID)&bmp))
return NULL;
BYTE *piexlsSrc = NULL;
LONG cbSize = bmp.bmWidthBytes * bmp.bmHeight;
piexlsSrc = new BYTE[cbSize];
BITMAPINFO bmpInfo = { 0 };
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = bmp.bmWidth;
bmpInfo.bmiHeader.biHeight = bmp.bmHeight;
bmpInfo.bmiHeader.biPlanes = bmp.bmPlanes;
bmpInfo.bmiHeader.biBitCount = bmp.bmBitsPixel;
bmpInfo.bmiHeader.biCompression = BI_RGB;
HDC hdcScreen = CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
LONG cbCopied = GetDIBits(hdcScreen, hBitmap, 0,
bmp.bmHeight, piexlsSrc, &bmpInfo, DIB_RGB_COLORS);
DeleteDC(hdcScreen);
if (0 == cbCopied)
{
delete[] piexlsSrc;
return NULL;
}
PixelFormat pf = bmp.bmBitsPixel == 32 ? PixelFormat32bppPARGB : PixelFormat24bppRGB;
Bitmap *pBitmap = new Bitmap(bmp.bmWidth, bmp.bmHeight, pf);
BitmapData bitmapData;
Rect rect(0, 0, bmp.bmWidth, bmp.bmHeight);
if (Ok != pBitmap->LockBits(&rect, ImageLockModeRead,
pf, &bitmapData))
{
delete pBitmap;
pBitmap = NULL;
return NULL;
}
BYTE *pixelsDest = (BYTE*)bitmapData.Scan0;
int nLinesize = (((bmp.bmBitsPixel*bmp.bmPlanes*bmp.bmWidth + 31) & ~31) >> 3);
int nHeight = bmp.bmHeight;
for (int y = 0; y < nHeight; y++)
{
memcpy_s((pixelsDest + y * nLinesize), nLinesize,
(piexlsSrc + (nHeight - y - 1) * nLinesize), nLinesize);
}
if (Ok != pBitmap->UnlockBits(&bitmapData))
{
delete pBitmap;
pBitmap = NULL;
}
delete[] piexlsSrc;
return pBitmap;
}