1

我正在尝试创建一个带有 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;
}
4

0 回答 0