windows 列表视图上的 ImageList 透明度?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/632622/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ImageList Transparency on Listviews?
提问by Irwin
EDIT:I've offered a bounty, since I doubt I'll be getting any answers otherwise.
编辑:我提供了赏金,因为我怀疑否则我会得到任何答案。
Lately I've been working with listviews and I've decided to add an iconfor each item indicating whether it's input or output. The icons add fine, but they're not transparent:
最近我一直在使用列表视图,我决定为每个项目添加一个图标,指示它是输入还是输出。图标添加得很好,但它们不透明:
As can be seen, the icons are clearly not transparent. I'm currently doing something like this load the icons:
可以看出,图标显然不透明。我目前正在做这样的事情加载图标:
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)));
}
I've tried messing with the flags for ImageList_Create
& LoadIcon
/LoadImage
but have had no luck and to be honest I've run out of ideas.
我试过搞乱ImageList_Create
& LoadIcon
/的标志,LoadImage
但没有运气,老实说我已经没有想法了。
Any help would be very appreciated.
任何帮助将不胜感激。
回答by Chris Becke
First up, ImageList_ReplaceIcon copies the icon data when adding it to an image list. So the HICON needs to be released afterwards.
首先,ImageList_ReplaceIcon 在将图标数据添加到图像列表时复制图标数据。所以HICON需要在之后发布。
Next, imagelists are natively bitmaps, not icons. And the way you are creating your imagelist makes the conversion of icon to bitmap very ambiguous. ILC_COLOR32 implies the imagelist should be created as a 32bit dib section, which typically contain transparency information via an embedded alpha channel. ILC_MASK instead implies that the internal bitmaps are DDB bitmaps, with the transparency information stored as a 1bpp mask bitmap.
其次,图像列表本身就是位图,而不是图标。您创建图像列表的方式使得图标到位图的转换非常模糊。ILC_COLOR32 意味着应该将图像列表创建为 32 位 dib 部分,它通常包含通过嵌入的 alpha 通道的透明度信息。ILC_MASK 相反暗示内部位图是 DDB 位图,透明度信息存储为 1bpp 掩码位图。
The quickest solution to your problem - take your two icons:
解决您问题的最快方法 - 带上您的两个图标:
- Merge them into a single bitmap resource thats 32 pels wide by 16 high. Fill the background with a mask color :- purple or something.
- Create the bitmap using ILC_COLOR|ILC_MASK
- Load the bitmap being sure NOT to use LR_TRANSPARENT.
- Add the bitmap using ImageList_AddMasked passing in a COLORREF that represents the mask color.
- 将它们合并为一个 32 像素宽 x 16 高像素的位图资源。用蒙版颜色填充背景:-紫色或其他颜色。
- 使用 ILC_COLOR|ILC_MASK 创建位图
- 加载位图确保不要使用 LR_TRANSPARENT。
- 使用 ImageList_AddMasked 添加位图,并传入表示遮罩颜色的 COLORREF。
OR, for a better visual effect...
或者,为了更好的视觉效果......
- export your PNG data as a 32x16 32bpp bitmap file containing pre-multiplied alpha channel data.
- Create the imagelist using the ILC_COLOR32 value.
- LoadImage() with LR_CREATEDIBSECTION to load the bitmap as a 32bpp dib section.
- Add the image using ImageList_Add()
- 将您的 PNG 数据导出为包含预乘 alpha 通道数据的 32x16 32bpp 位图文件。
- 使用 ILC_COLOR32 值创建图像列表。
- LoadImage() 和 LR_CREATEDIBSECTION 将位图加载为 32bpp dib 部分。
- 使用 ImageList_Add() 添加图像
(the last option is kind of tricky as the number of tools that support writing out 32bit bmp files with properly pre multiplied alpha channels is rather low).
(最后一个选项有点棘手,因为支持用适当的预乘 alpha 通道写出 32 位 bmp 文件的工具数量相当少)。
Edited to add the following code sample. Using a 4bpp bitmap created in the dev environment this works just great :-
编辑以添加以下代码示例。使用在开发环境中创建的 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);
回答by i_am_jorf
You want to make your icons have a background color that isn't used anywhere else in the icon, like a really ugly purple, and then use LoadImage(..., LR_LOADTRANSPARENT); The flag says look at the first pixel at 0,0 and make everything that color transparent.
您想让您的图标具有图标中其他任何地方都没有使用的背景颜色,例如非常丑陋的紫色,然后使用 LoadImage(..., LR_LOADTRANSPARENT); 标志说在 0,0 处查看第一个像素并使所有颜色透明。
回答by Murray
Your code looks fine to me, I always use LoadImage instead of LoadIcon but I suspect that doesn't matter. Have you checked that the icons do indeed have transparent areas and don't themselves have a solid background?
您的代码对我来说看起来不错,我总是使用 LoadImage 而不是 LoadIcon 但我怀疑这无关紧要。您是否检查过图标确实具有透明区域并且它们本身没有纯色背景?
My LoadImage calls look like:
我的 LoadImage 调用看起来像:
HICON hIcon = (HICON)LoadImage(hinstResources,MAKEINTRESOURCE(IDI_ICON),IMAGE_ICON,16,16,LR_DEFAULTCOLOR);
回答by LarryF
Here... Create an ImageList, as suggested, make your icons into a Bitmap, 16 pixels high, by 16*n long, where n= the number of icons...
在这里...创建一个 ImageList,按照建议,将您的图标变成一个位图,高 16 像素,长 16*n,其中 n= 图标的数量...
Set the background color to 255, 0, 255, like you have done.
将背景颜色设置为 255、0、255,就像您所做的那样。
Then, load it, and add it to the image list as I did here:
然后,加载它,并将其添加到图像列表中,就像我在这里所做的那样:
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);
Of course, this was written in MFC, but as you know, it's just a wrapper to Win32...
当然,这是用 MFC 编写的,但如您所知,它只是 Win32 的包装器......
Outside of this, you are going to have to go to a custom draw control, in which you draw the icon over whatever background the icon happens to be sitting on. There isn't really any magic "transparent" color, that I know of, in any of these controls.
除此之外,您将不得不进入自定义绘制控件,在该控件中,您可以在图标恰好位于的任何背景上绘制图标。在这些控件中的任何一个中,都没有我所知道的任何神奇的“透明”颜色。
In the case of a custom draw, you need to use code like the following:
在自定义绘制的情况下,您需要使用如下代码:
#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;
This code decides where to draw the icon, and takes a snapshot of the background, creates a mask for the icon, and then draws it over the background, giving it a fully transparent background...
此代码决定在何处绘制图标,并拍摄背景快照,为图标创建蒙版,然后将其绘制在背景上,为其提供完全透明的背景...
Hope that helps somewhat. If not, please explain in more detail what you are trying to make happen, and what you are seeing, or what you are NOT seeing...
希望有所帮助。如果没有,请更详细地解释您要实现的目标,以及您所看到的或未看到的...