Windows ListView上的ImageList透明度?

Windows ListView上的ImageList透明度?,windows,winapi,transparency,Windows,Winapi,Transparency,编辑:我提供了一笔赏金,因为我怀疑我是否会得到任何答案 最近我一直在使用ListView,我决定为每个项目添加一个图标,指示它是输入还是输出。图标添加得很好,但不是透明的: 可以看出,图标显然是不透明的。我正在做这样的事情加载图标: hImageList = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR32, 2, 2); if (hImageList != NULL) { iIN = ImageList_AddIcon(hI

编辑:我提供了一笔赏金,因为我怀疑我是否会得到任何答案

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

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

  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\u Create
&
LoadIcon
/
LoadImage
的标志,但是运气不好,老实说,我已经没有主意了


非常感谢您的帮助。

您希望使您的图标具有图标中其他任何位置都不使用的背景色,例如非常难看的紫色,然后使用LoadImage(…,LR_LOADTRANSPARENT);该标志表示,请查看0,0处的第一个像素,并使所有颜色透明。

您的代码在我看来很好,我总是使用LoadImage而不是LoadIcon,但我怀疑这并不重要。你有没有检查过图标确实有透明的区域,并且它们本身没有坚实的背景

我的LoadImage调用如下所示:

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

首先,ImageList_ReplaceIcon在将图标数据添加到图像列表时复制图标数据。因此HICON需要在之后释放

接下来,图像列表是本机位图,而不是图标。创建图像列表的方式使得图标到位图的转换非常模糊。ILC_COLOR32意味着应将imagelist创建为32位dib部分,该部分通常通过嵌入式alpha通道包含透明度信息。ILC_掩码表示内部位图是DDB位图,透明度信息存储为1bpp掩码位图

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

  • 将它们合并到一个32像素宽16像素高的位图资源中。用遮罩颜色填充背景:-紫色或其他颜色
  • 使用ILC|U颜色| ILC|U遮罩创建位图
  • 加载位图,确保不使用LR_透明
  • 使用ImageList\u AddMasked添加位图,并传入表示遮罩颜色的COLORREF
或者,为了更好的视觉效果

  • 将PNG数据导出为32x16 32bpp位图文件,其中包含预乘的alpha通道数据
  • 使用ILC_COLOR32值创建imagelist
  • LoadImage()和LR_CREATEDIBSECTION可将位图作为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);

这里。。。按照建议创建一个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;
这段代码决定在何处绘制图标,并拍摄背景快照,为图标创建一个遮罩,然后在背景上绘制图标,给它一个完全透明的背景


希望这能有所帮助。如果没有,请更详细地解释您正试图实现的目标,以及您正在看到或没有看到的内容…

我已经尝试过(第一个像素为RGB(255,0,255)),并引用了文档:LR_LOADTRANSPARENT不会透明地加载图像。它创建一个不透明的图像列表,该列表仅显示为透明,因为所有背景像素都已更改为“颜色”窗口。啊,是的,这很有意义。愚蠢的窗口和透明的图标。正如我在原始帖子中所说的,我已经弄乱了LoadIcon和LoadImage。我还尝试仅使用LR_DEFAULTCOLOR标志,但没有任何区别。哦,是的,我的图标是透明的:我今天早些时候尝试了第一个选项,我也遇到了同样的问题。在读了你的帖子后,我尝试了第二种方法,结果完全没有什么不同。请看一下:当您提供ILC|U掩码| ILC|U颜色时,您是如何加载位图的?您可能应该忽略DIBSECTION标志,并且还要注意将位图加载到DDB曲面是有损的,因此描述文件中理想RGB值的COLORREF不能与DDB中的像素匹配。使用纯色…你完全忽略了对第二个选项的任何评论。此外,我确实省略了第一个选项的LR_CREATEDIBSECTION标志。我的蒙版颜色是粉红色(RGB(255,0,255)),因此没有任何匹配项。很遗憾,我无法在工作时将你的bmp文件作为im下载,而且还有一个websense过滤器。也就是说,从制作一个简单的16色位图开始。我不能评论第二个选项不起作用,因为它要复杂得多,而且它可能失败的地方也不太明显。你的32bpp argb位图有紫色背景。如屏幕截图所示,背景显示为白色。这意味着,在掩模和32bpp的情况下,imagelist项的alpha’d是正确的——相对于白色bk。问题是——交替的灰色填充是如何完成的?你有你的来源可供我们处理吗?我看到一些评论,人们正在测试你的代码。。我很想看一看,因为我在这方面做了很多工作…请看我的答案