我正在尝试创建一个带有 5 个“不可见”按钮的启动器窗口,这些按钮的中心有一个较小的部分透明图像。里面的图像会根据用户是否将鼠标悬停在按钮上而发生变化。在此示例中,图像是资源 IDB_Website1 和 IDB_Website2。
图像为 .png 格式。我正在使用 GDI+ 并使用http://www.codeproject.com/Articles/3537/Loading-JPG-PNG-resources-using-GDI从资源中加载 PNG 文件。
我使用 BS_OWNERDRAW 来处理按钮的图形。问题是我不知道如何将“资源中的 PNG”代码链接到父级的 WM_DRAWITEM。使用我目前完成代码的方式,我通过 HBITMAP 失去了 .png 的透明度。
全局变量:
HBITMAP globalpic;
主要的wndproc:
case WM_CREATE:
{
HWND hwndButton = CreateWindow(TEXT("button"), NULL,
WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
190, 230, 260, 50, // <- the larger rect size
hWnd, (HMENU) HT_BUTTON1, hInst, NULL);
HTButton = (WNDPROC) SetWindowLong(hwndButton, GWL_WNDPROC, (LONG) ButtonProc);
}
case WM_DRAWITEM:
{
DRAWITEMSTRUCT* lpDrawItem = (DRAWITEMSTRUCT*)lParam;
HBITMAP hBmp;
HDC hdc = CreateCompatibleDC(NULL);
if (hovering) // <- mousehover detection, not included
{
gdi.CreateBM(IDB_Website2, _T("PNG"), hInst, hdc, 62, 100, 200, 40);
} else {
gdi.CreateBM(IDB_Website1, _T("PNG"), hInst, hdc, 62, 100, 200, 40);
}
hBmp = globalpic; // get the global var gdi.CreateBM created
DeleteDC(hdc);
BITMAP bm;
GetObject(hBmp, sizeof(bm), &bm);
HDC hMemDC = CreateCompatibleDC(NULL);
HBITMAP hOldBmp = (HBITMAP)SelectObject(hMemDC, hBmp);
StretchBlt (lpDrawItem->hDC,
lpDrawItem->rcItem.left + 30,
lpDrawItem->rcItem.top + 5,
200, <- the width of image
40, <- the height of image
hMemDC,
0, 0,
bm.bmWidth,
bm.bmHeight,
SRCCOPY);
SelectObject(hMemDC, hOldBmp);
DeleteDC(hMemDC);
DeleteObject(hBmp);
break;
}
类 GDI 的方法 CreateBM。
目前,由于我不知道更好的方法,它将 HBITMAP 发送到全局变量 globalpic。问题是这样做,我失去了透明度。
void CreateBM(UINT menuid, LPCTSTR pType, HMODULE hInst, HDC hdc, int x, int y, int w, int h)
{
CGdiPlusBitmapResource m_pBitmap;
m_pBitmap.Load(menuid, pType, hInst);
m_pBitmap.m_pBitmap->GetHBITMAP(RGB(255, 255, 0), &globalpic);
//m_pBitmap.m_pBitmap->GetHBITMAP(GetBkColor(hdc), &globalpic); // <- no-go either
}
有什么办法可以更直接地做到这一点?我觉得通过 HBITMAP 路线是完全没有必要的,但我一生都无法弄清楚我应该怎么做。
再说一次,如果使用 HBITMAP 方式很好,任何关于我如何使颜色(我猜 (RGB(255, 255, 0) ...?)在当前实现中透明的指针?
回复汉斯:
我也有一个像这样的 GDI 方法,但它目前没有使用,因为我无法在绘制后删除图像(悬停更改图像时需要):
void Create(UINT menuid, LPCTSTR pType, HMODULE hInst, HDC hdc, int x, int y, int w, int h)
{
Graphics grpx(hdc);
ht_img = new CGdiPlusBitmapResource();
ht_img -> Load(menuid, pType, hInst);
grpx.DrawImage(*ht_img, x, y, w, h);
delete ht_img;
}