光标资源,在这里指的是资源类型为RT_CURSOR的资源信息。通过ResHacker看到的效果图如下:
解析代码如下:
HRSRC hResrc = ::FindResourceEx((HMODULE)hModule, lpType, lpName, wLanguage);
DWORD dwSize = ::SizeofResource((HMODULE)hModule, hResrc);
HGLOBAL hGlobal = ::LoadResource((HMODULE)hModule, hResrc);
if (hGlobal == NULL)
return;
BYTE* lpResrc = (BYTE*)LockResource(hGlobal);
if (lpResrc == NULL)
return;
HCURSOR hCursor = (HCURSOR)CreateIconFromResource((PBYTE)lpResrc, dwSize, FALSE, 0x00030000);
if (hCursor)
{
m_imagelist.Add(hCursor);
Gdiplus::Bitmap* pBitmap = HCursor2GdiplusBitmap(hCursor);
if (pBitmap && pBitmap->GetLastStatus() == Gdiplus::Ok)
{
//解析成功
}
}
光标文件图像层分为2层,第一层为掩码层(遮罩层,白色为透明像素点),第二层为图像层,2个图层进行叠加达到光标不规则透明效果。这里用到了一个转换函数HCursor2GdiplusBitmap,实现代码如下:
Gdiplus::Bitmap* HCursor2GdiplusBitmap(HCURSOR hCursor)
{
ICONINFO iconinfo;
if (GetIconInfo(hCursor, &iconinfo))
{
Gdiplus::Bitmap* pImage = (Gdiplus::Bitmap*)Bitmap::FromHBITMAP(iconinfo.hbmMask, NULL);
Gdiplus::Status result = pImage->GetLastStatus();
if (result == Gdiplus::Ok)
{
CSize sz(pImage->GetWidth(), pImage->GetHeight());
sz.cy /= 2;
Gdiplus::Bitmap* pResult = new Gdiplus::Bitmap(sz.cx, sz.cy);
Gdiplus::Graphics graphics(pResult);
graphics.DrawImage(pImage, Rect(0, 0, sz.cx, sz.cy), 0, sz.cy, sz.cx, sz.cy, UnitPixel);
// 下面将遮挡层白色透明处理
Gdiplus::Bitmap* pSrcImage = new Gdiplus::Bitmap(sz.cx, sz.cy);
Gdiplus::Graphics g(pSrcImage);
g.DrawImage(pImage, Rect(0, 0, sz.cx, sz.cy), 0, 0, sz.cx, sz.cy, UnitPixel);
PixelFormat pixfmt = pSrcImage->GetPixelFormat();
if (!Gdiplus::IsAlphaPixelFormat(pixfmt))
{
delete pResult;
delete pSrcImage;
delete pImage;
return NULL;
}
for (int i = 0; i < sz.cy; i++)
{
for (int j = 0; j < sz.cx; j++)
{
Color clrSrc, clrDst;
pSrcImage->GetPixel(j, i, &clrSrc);
const unsigned red = clrSrc.GetRed();
const unsigned green = clrSrc.GetGreen();
const unsigned blue = clrSrc.GetBlue();
const unsigned alpha = clrSrc.GetAlpha();
pResult->GetPixel(j, i, &clrDst);
if (red == 255 && green == 255 && blue == 255)// 颜色值白色
{
clrDst.SetValue(Color::MakeARGB(0, clrDst.GetRed(), clrDst.GetGreen(), clrDst.GetBlue()));
pResult->SetPixel(j, i, clrDst);
}
}
}
delete pSrcImage;
delete pImage;
return pResult;
}
}
return NULL;
}