编辑: 我已经提供了赏金,因为我怀疑否则我不会得到任何答案。

最近我一直在使用列表视图,我决定添加一个 图标 对于每个项目,指示它是输入还是输出。图标添加得很好,但它们不透明:

Example of icon not being transparent

可以看到,图标显然不是透明的。我目前正在做这样的事情加载图标:

  hImageList = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR32, 2, 2);
  if (hImageList != NULL)
  {
    iIN  = ImageList_AddIcon(hImageList, LoadIcon(hInstance, MAKEINTRESOURCE(101)));
    iOUT = ImageList_AddIcon(hImageList, LoadIcon(hInstance, MAKEINTRESOURCE(102)));
  }

我尝试过弄乱标志 ImageList_Create & LoadIcon/LoadImage 但运气不好,说实话我已经没有想法了。

任何帮助将不胜感激。

有帮助吗?

解决方案

首先,ImageList_ReplaceIcon 在将图标添加到图像列表时会复制图标数据。所以HICON需要事后发布。

其次,图像列表本身就是位图,而不是图标。创建图像列表的方式使得图标到位图的转换非常模糊。ILC_COLOR32 意味着图像列表应创建为 32 位 dib 部分,通常通过嵌入的 Alpha 通道包含透明度信息。ILC_MASK 相反意味着内部位图是 DDB 位图,透明度信息存储为 1bpp 掩码位图。

解决您的问题的最快方法 - 使用您的两个图标:

  • 将它们合并为 32 像素宽 x 16 高像素的单个位图资源。用遮罩颜色填充背景:- 紫色或其他颜色。
  • 使用 ILC_COLOR|ILC_MASK 创建位图
  • 加载位图时确保不使用 LR_TRANSPARENT。
  • 使用 ImageList_AddMasked 添加位图,传入表示蒙版颜色的 COLORREF。

或者,为了更好的视觉效果......

  • 将 PNG 数据导出为包含预乘 Alpha 通道数据的 32x16 32bpp 位图文件。
  • 使用 ILC_COLOR32 值创建图像列表。
  • 使用 LR_CREATEDIBSECTION 的 LoadImage() 将位图加载为 32bpp dib 部分。
  • 使用 ImageList_Add() 添加图像

(最后一个选项有点棘手,因为支持使用正确预乘的 alpha 通道写出 32 位 bmp 文件的工具数量相当少)。


编辑以添加以下代码示例。使用在开发环境中创建的 4bpp 位图,效果非常好:-

HWND hwndCtl = CreateWindowEx(0,WC_LISTVIEW,TEXT("ListView1"),WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL,0,0,cx,cy,hWnd,(HMENU)101,hModule,NULL);
HBITMAP hbm = (HBITMAP)LoadImage(hModule,MAKEINTRESOURCE(IDB_BITMAP1),IMAGE_BITMAP,0,0,0);
COLORREF crMask=RGB(255,0,255);
HIMAGELIST himl = ImageList_Create(16,16,ILC_COLOR|ILC_MASK,2,0);
ImageList_AddMasked(himl,hbm,crMask);
ListView_SetImageList(hwndCtl,himl,LVSIL_NORMAL);

其他提示

你想让你的图标有一个背景颜色,不会在图标的任何其他地方使用,比如一个非常难看的紫色,然后使用LoadImage(...,LR_LOADTRANSPARENT);标志说看0,0处的第一个像素,并使所有颜色都透明。

您的代码对我来说很好,我总是使用LoadImage而不是LoadIcon,但我怀疑这无所谓。您是否检查过图标确实具有透明区域并且本身没有可靠的背景?

我的LoadImage调用如下:

HICON hIcon = (HICON)LoadImage(hinstResources,MAKEINTRESOURCE(IDI_ICON),IMAGE_ICON,16,16,LR_DEFAULTCOLOR);

这里......按照建议创建一个ImageList,将你的图标变成一个16位高,16 * n长的位图,其中n =图标数...

将背景颜色设置为255,0,255,就像您所做的那样。

然后,加载它,并像我在这里一样将它添加到图像列表中:

 m_ImageList.Create(16, 16, ILC_COLOR16 | ILC_MASK, 7, 1);
 CBitmap bm;
 bm.LoadBitmap(IDB_SUPERTREEICONS);
 m_ImageList.Add(&bm, RGB(255, 0, 255));
 GetTreeCtrl().SetImageList(&m_ImageList, TVSIL_NORMAL);

当然,这是用MFC编写的,但是如你所知,它只是Win32的一个包装器......

除此之外,您将不得不转到自定义绘图控件,在该控件中,您可以在图标恰好位于的任何背景上绘制图标。实际上没有任何魔法“透明”。我所知道的颜色,在任何这些控制中。

如果是自定义绘图,则需要使用以下代码:

#define TRANSPARENT_COLOR (255,0,255)

UINT iBitmap = IDB_ICON_UP
CDC *dc = GetDC();
int x = 0, y = 0;

    CDC *pDisplayMemDC = new CDC;
    CDC *pMaskDC = new CDC;
    CDC *pMemDC = new CDC;
    CBitmap *pBitmap = new CBitmap;
    CBitmap *pMaskBitmap = new CBitmap;
    CBitmap *pMemBitmap = new CBitmap;
    int cxLogo, cyLogo;
    BITMAP bm;

    pBitmap->LoadBitmap(iBitmap);
    pDisplayMemDC->CreateCompatibleDC(dc);
    CBitmap *pOldBitmap = (CBitmap *)pDisplayMemDC->SelectObject(pBitmap);

    pBitmap->GetObject(sizeof(bm), &bm);
    cxLogo = bm.bmWidth;
    cyLogo = bm.bmHeight;

    pMaskBitmap->CreateBitmap(cxLogo, cyLogo, 1, 1, NULL);
    pMaskDC->CreateCompatibleDC(dc);
    CBitmap *pOldMask = (CBitmap *)pMaskDC->SelectObject(pMaskBitmap);
    COLORREF oldBkColor = pDisplayMemDC->SetBkColor(TRANSPARENT_COLOR);
    pMaskDC->BitBlt(0, 0, cxLogo, cyLogo, pDisplayMemDC, 0, 0, SRCCOPY);

    pMemBitmap->CreateCompatibleBitmap(dc, cxLogo, cyLogo);
    pMemDC->CreateCompatibleDC(dc);
    CBitmap *pOldMem = (CBitmap *)pMemDC->SelectObject(pMemBitmap);

    pMemDC->BitBlt(0, 0, cxLogo, cyLogo, dc,            x, y, SRCCOPY);
    pMemDC->BitBlt(0, 0, cxLogo, cyLogo, pDisplayMemDC, 0, 0, SRCINVERT);
    pMemDC->BitBlt(0, 0, cxLogo, cyLogo, pMaskDC,       0, 0, SRCAND);
    pMemDC->BitBlt(0, 0, cxLogo, cyLogo, pDisplayMemDC, 0, 0, SRCINVERT);
        dc->BitBlt(x, y, cxLogo, cyLogo, pMemDC,        0, 0, SRCCOPY);

    delete pMemDC->SelectObject(pOldMem);
    delete pMemDC;

    delete pMaskDC->SelectObject(pOldMask);
    delete pMaskDC;

    delete pDisplayMemDC->SelectObject(pOldBitmap);
    delete pDisplayMemDC;

此代码决定在何处绘制图标,并拍摄背景的快照,为图标创建遮罩,然后将其绘制在背景上,为其提供完全透明的背景......

希望有所帮助。如果没有,请详细解释你想要发生什么,你所看到的,或者你没看到的......

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top