PE文件资源解析(四)光标资源的解析

光标资源,在这里指的是资源类型为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;
}

猜你喜欢

转载自blog.csdn.net/u012156872/article/details/105662974