Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何将透明PNG添加为工具栏图标?_C++_Winapi_Png_Bmp_Imagelist - Fatal编程技术网

C++ 如何将透明PNG添加为工具栏图标?

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

我的目的是在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 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

  • ID\u IMG\u SPAWN
    的资源更改为32位位图


事实上,要正确显示32位位图,您必须:

  • ILC\u COLOR24
    更改为
    ILC\u COLOR32

  • ID\u IMG\u SPAWN
    的资源更改为具有预乘alpha的32位位图

  • 加载时为位图创建一个DIB部分

(Win32的格式要求非常严格)


问:如何创建位图的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

步骤是

  • 在Pixelformer中打开图像(任何格式),然后从菜单中选择“导出”
  • 选择A8:R8:G8:B8(32bpp)和预乘Alpha,然后单击确定
  • 然后你可以保存你的BMP文件!将此BMP文件导入Visual Studio资源,替换以前的24位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);
    
    如下所示,这种方法效果良好


    我在上面回答了这些问题