C++ 如何将透明PNG添加为工具栏图标?
我的目的是在Win32中创建一个包含透明图标的工具栏。我尝试使用以下代码创建一个简单的工具栏,其中一个按钮具有自定义图像:C++ 如何将透明PNG添加为工具栏图标?,c++,winapi,png,bmp,imagelist,C++,Winapi,Png,Bmp,Imagelist,我的目的是在Win32中创建一个包含透明图标的工具栏。我尝试使用以下代码创建一个简单的工具栏,其中一个按钮具有自定义图像: //创建工具栏 HWND hToolbar=CreateWindow(工具栏类名, 无效的 WS|u CHILD | TBSTYLE|u FLAT | TBSTYLE|u AUTOSIZE | TBSTYLE|u LIST | CCS|u BOTTOM, 0, 0, 0, 0, hwnd, 无效的 ghInstance,//*/MAKEINTRESOURCE(ID\u IM
//创建工具栏
HWND hToolbar=CreateWindow(工具栏类名,
无效的
WS|u CHILD | TBSTYLE|u FLAT | TBSTYLE|u AUTOSIZE | TBSTYLE|u LIST | CCS|u BOTTOM,
0, 0, 0, 0,
hwnd,
无效的
ghInstance,//*/MAKEINTRESOURCE(ID\u IMG\u SPAWN),
图像/位图,
32, 32,
空);
ImageList_AddMasked(hImagelist,
位图,
RGB(255255)/*白色为透明色*/);
发送消息(hToolbar,
TB_SETIMAGELIST,
静态_-cast(0),
(LPARAM)hImagelist);
ImageList\u Create
仅支持24位位图,这意味着没有用于透明度的alpha通道。但是,我可以通过ImageList\u AddMasked
使用遮罩颜色来模拟透明度效果。(这里,我将白色(RGB(255,255,255)
)设置为遮罩颜色。)
这样做效果很好,但是这种方式显示的图像非常尖锐/锯齿状,因为alpha通道中缺少粒度(每个像素要么透明,要么完全不透明)
我知道PNG格式可以解决这个问题,因为它提供了一个真正的alpha通道。我知道Win32 ImageList支持PNG格式,但我不知道如何正确使用它。(PNG资源可以添加到VisualStudio资源中,但我不知道如何从代码中使用它们。)
我找不到任何方法使LoadImage
加载PNG。唯一支持的类型是IMAGE\u位图
IMAGE\u光标
和IMAGE\u图标
。我将资源(ID\u IMG\u SPAWN
)更改为一个PNG文件,并逐一尝试了这三种类型,但都只得到了如下空白显示:
ID_PNG1 RCDATA "file.png"
有人能帮我吗?如何使用
LoadImage
加载透明PNG并将其用作工具栏图像?LoadImage
在尝试加载PNG资源时将返回NULL
您可以将PNG资源添加为图标。否则,请使用Windows Imaging Component或Gdiplus+加载png资源
阅读PNG资源,如下所示:
HBITMAP loadimage(HINSTANCE hinst, const wchar_t* name)
{
HBITMAP hbitmap = NULL;
ULONG_PTR token;
Gdiplus::GdiplusStartupInput tmp;
Gdiplus::GdiplusStartup(&token, &tmp, NULL);
if(auto hres = FindResource(hinst, name, RT_RCDATA))
if(auto size = SizeofResource(hinst, hres))
if(auto data = LockResource(LoadResource(hinst, hres)))
if(auto stream = SHCreateMemStream((BYTE*)data, size))
{
Gdiplus::Bitmap bmp(stream);
stream->Release();
bmp.GetHBITMAP(Gdiplus::Color::Transparent, &hbitmap);
}
Gdiplus::GdiplusShutdown(token);
return hbitmap;
}
...
auto hbitmap = loadimage(ghinst, MAKEINTRESOURCE(ID_PNG1 ));
if(hbitmap)
{
ImageList_AddMasked(himage, hbitmap, 0);
DeleteObject(hbitmap);
}
资源定义应如下所示:
ID_PNG1 RCDATA "file.png"
ImageList_Create仅支持24位位图,这意味着没有用于透明度的alpha通道
不,那是错的ImageList\u Create
还支持32位位图
因为您打算在Win32中创建包含透明图标的工具栏,所以根本不需要加载PNG。如果你想要PNG,你可能需要像@barmak所说的那样与GdiPlus合作
32位位图的ALPHA值为8位。使用32位位图可以产生与PNG相同的效果
当您执行以下操作时,您说您的按钮图像显示为空白:
- 将
更改为ILC\u COLOR24
ILC\u COLOR32
- 将
的资源更改为32位位图ID\u IMG\u SPAWN
事实上,要正确显示32位位图,您必须:
- 将
更改为ILC\u COLOR24
ILC\u COLOR32
- 将
的资源更改为具有预乘alpha的32位位图ID\u IMG\u SPAWN
- 加载时为位图创建一个DIB部分
问:如何创建位图的DIB部分 A:在
LoadImage
的最后一个参数中指定LR\u CREATEDIBSECTION
说明:
LoadImage((HINSTANCE)GetWindowLong(hwnd,GWL\u HINSTANCE),MAKEINTRESOURCE(ID\u IMG\u SPAWN),IMAGE\u位图,32,32,NULL)
这是LoadImage
函数的代码。请参见,要创建DIB节,只需在LoadImage
的最后一个参数中指定LR\u CREATEDIBSECTION
问:如何获得具有预乘alpha的BMP 答:可以帮助您将alpha通道文件转换为预乘alpha BMP 步骤是
然后,您不需要再使用
ImageList\u AddMasked
(这会使图像清晰),因为您的32位BMP中已经有了一个可识别的ALPHA。因此,直接使用ImageList\u Add
好的,在上面解释的操作之后,您的代码应该是:
//创建工具栏
HWND hToolbar=CreateWindow(工具栏类名,NULL,
WS|u CHILD | TBSTYLE|u FLAT | TBSTYLE|u AUTOSIZE | TBSTYLE|u LIST | CCS|u BOTTOM,
0,0,0,0,hwnd,NULL,ghInstance,NULL);
//设置字体(这不是问题所在)
SendMessage(hToolbar,WM_SETFONT,(WPARAM)hFontBold,
静态_cast(MAKELONG(TRUE,0));
自动hImagelist=
ImageList_Create(32,32,ILC_COLOR32/*不需要遮罩。更改为ILC_COLOR32.*/,1,0);
HBITMAP bitmap=static_cast(LoadImage((HINSTANCE))GetWindowLong(hwnd,
GWL_HINSTANCE)、MAKEINTRESOURCE(ID_IMG_SPAWN)、图像_位图、,
32,32,LR_CREATEDIBSECTION/*这很重要*/);
ImageList_Add(hImagelist,位图,NULL);
SendMessage(hToolbar、TB_SETIMAGELIST、静态_cast(0)、(LPRAM)hImagelist);
如下所示,这种方法效果良好
我在上面回答了这些问题