我的目的是在Win32中创建一个包含透明图标的工具栏。我尝试了以下代码来创建一个具有自定义图像的按钮的简单工具栏:
// Create the toolbar
HWND hToolbar = CreateWindow(TOOLBARCLASSNAME,
NULL,
WS_CHILD | TBSTYLE_FLAT | TBSTYLE_AUTOSIZE | TBSTYLE_LIST | CCS_BOTTOM,
0, 0, 0, 0,
hwnd,
NULL,
ghInstance, // <-this is the HINSTANCE of the application
NULL);
// Set the font (this cannot be the problem)
SendMessage(hToolbar,
WM_SETFONT,
(WPARAM)hFontBold,
static_cast<LPARAM>(MAKELONG(TRUE, 0)));
auto hImagelist = ImageList_Create(32, 32,ILC_COLOR24 | ILC_MASK, 1, 0);
HBITMAP bitmap = static_cast<HBITMAP>(LoadImage(ghInstance,
/* ID_IMG_SPAWN is my custom resource -> */ MAKEINTRESOURCE(ID_IMG_SPAWN),
IMAGE_BITMAP,
32, 32,
NULL));
ImageList_AddMasked(hImagelist,
bitmap,
RGB(255,255,255) /* white is the transparent color */);
SendMessage(hToolbar,
TB_SETIMAGELIST,
static_cast<WPARAM>(0),
(LPARAM)hImagelist);
ImageList_Create
只支持24位位图,这意味着没有透明的alpha通道.但是,我可以通过ImageList_AddMasked
使用掩膜颜色来模拟透明效果。(在这里,我将白色(RGB(255, 255, 255)
)设置为掩膜颜色。)
这很好,但是这样显示的图像非常锐利/锯齿状,因为alpha通道中缺少粒度(每个像素都是透明的或完全不透明的)。
我知道PNG格式可以解决这个问题,因为它提供了一个真正的alpha通道。我知道Win32 ImageLists支持PNG格式,但我不知道如何正确使用它。(可以将PNG资源添加到Visual资源中,但我不知道如何从代码中使用它们。)
我找不到让LoadImage
加载PNG的任何方法。唯一受支持的类型是IMAGE_BITMAP
、IMAGE_CURSOR
和IMAGE_ICON
。我将资源(ID_IMG_SPAWN
)更改为PNG文件,并逐一尝试了这三种类型中的每一种类型,但都只产生了这样的空白显示:
有人能帮我吗?如何使用LoadImage
加载透明的PNG并将其用作工具栏映像?
发布于 2019-11-09 02:05:47
ImageList_Create只支持24位位图,这意味着没有透明的alpha通道.
不,那是不对的。ImageList_Create
支持32位位图以及。
因为您打算在Win32中创建一个包含透明图标的工具栏,所以根本不需要加载一个PNG。如果你想要PNG,你可能需要和GdiPlus合作,就像barmak说的那样。
32位位图有8位的阿尔法.使用32位位图可以产生与PNG相同的效果.
当你这样做的时候,你说你的按钮图像是空白的:
ILC_COLOR24
改为ILC_COLOR32
ID_IMG_SPAWN
的资源更改为32位位图实际上,要正确显示32位位图,您必须:
ILC_COLOR24
更改为ILC_COLOR32
ID_IMG_SPAWN
的资源更改为32位位图,并使用预乘的α.(Win32 32的格式要求非常严格)
问:如何创建位图的DIB部分?
A:在LR_CREATEDIBSECTION
的最后一个参数中指定LoadImage
。
解释:
LoadImage((HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),MAKEINTRESOURCE(ID_IMG_SPAWN), IMAGE_BITMAP,32, 32,NULL)
这是LoadImage
函数的代码。请参阅LoadImage的MSDN文档,要创建DIB部分,只需在LoadImage
的最后一个参数中指定LR_CREATEDIBSECTION
。
问:如何获得具有预乘α的BMP?
答:皮克塞尔器可以帮助你把你的α通道文件转换成一个前置的-α- BMP.
步骤如下
然后你可以保存你的BMP文件!将此BMP文件导入Visual资源,替换以前的24位BMP。
然后,您不再需要使用ImageList_AddMasked
(它使图像清晰),因为您已经在您的32位BMP中有一个可识别的ALPHA。所以,直接使用ImageList_Add
。
好的,在上面解释的操作之后,您的代码应该如下:
// Create the toolbar
HWND hToolbar = CreateWindow(TOOLBARCLASSNAME,NULL,
WS_CHILD | TBSTYLE_FLAT | TBSTYLE_AUTOSIZE | TBSTYLE_LIST | CCS_BOTTOM,
0, 0, 0, 0, hwnd, NULL, ghInstance, NULL);
// Set the font (this cannot be the problem)
SendMessage(hToolbar, WM_SETFONT, (WPARAM)hFontBold,
static_cast<LPARAM>(MAKELONG(TRUE, 0)));
auto hImagelist =
ImageList_Create(32, 32,ILC_COLOR32 /*DON'T NEED THE MASK. CHANGED TO ILC_COLOR32.*/, 1, 0);
HBITMAP bitmap = static_cast<HBITMAP>(LoadImage((HINSTANCE)GetWindowLong(hwnd,
GWL_HINSTANCE), MAKEINTRESOURCE(ID_IMG_SPAWN), IMAGE_BITMAP,
32, 32, LR_CREATEDIBSECTION /*THIS IS IMPORTANT*/ ));
ImageList_Add(hImagelist, bitmap, NULL);
SendMessage(hToolbar, TB_SETIMAGELIST, static_cast<WPARAM>(0), (LPARAM)hImagelist);
这件事做得不错,如下所示。
我上面回答的这些问题足以解决这个问题。
发布于 2019-11-07 17:34:27
当试图加载PNG资源时,LoadImage
将返回NULL
。
您可以添加您的PNG资源作为图标。否则,使用或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"
https://stackoverflow.com/questions/58751417
复制相似问题