gpt4 book ai didi

c++ - 如何添加透明 PNG 作为工具栏图标?

转载 作者:行者123 更新时间:2023-12-02 04:00:07 24 4
gpt4 key购买 nike

我的目的是在 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 channel 。不过,我可以通过 ImageList_AddMasked 使用 mask 颜色来模拟透明效果。 (在这里,我将 mask 颜色设置为白色 (RGB(255, 255, 255))。)

效果很好,但由于 Alpha channel 缺乏粒度(每个像素要么透明,要么完全不透明),所以以这种方式显示的图像极其锐利/锯齿状

我知道 PNG 格式可以解决这个问题,因为它提供了真正的 Alpha channel 。我知道Win32 ImageLists支持PNG格式,但我不知道如何正确使用它。 (PNG资源可以添加到Visual Studio资源中,但我不知道如何从代码中使用它们。)

我找不到任何方法让 LoadImage 加载 PNG。唯一支持的类型是 IMAGE_BITMAP IMAGE_CURSORIMAGE_ICON。我将资源 (ID_IMG_SPAWN) 更改为 PNG 文件,并一一尝试了这三种类型,但所有结果都只是显示空白,如下所示:

谁能帮帮我吗?如何使用 LoadImage 加载透明 PNG 并将其用作工具栏图像?

最佳答案

ImageList_Create only supports 24-bit bitmaps, which means there is no alpha channel for transparency.

不,那是错误的。 ImageList_Create 也支持 32 位位图

由于您打算在 Win32 中创建一个包含透明图标的工具栏,因此您根本不需要加载 PNG。如果您想要 PNG,您可能必须像 @barmak 所说的那样使用 GdiPlus。

32 位位图有 8 位用于 ALPHA。使用 32 位位图可以达到与 PNG 相同的效果。

<小时/>

您说,当您执行以下操作时,按钮图像显示为空白:

  • ILC_COLOR24 更改为 ILC_COLOR32

  • ID_IMG_SPAWN的资源更改为32位位图

<小时/>

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

  • ILC_COLOR24 更改为 ILC_COLOR32

  • ID_IMG_SPAWN的资源更改为带有预乘alpha的32位位图

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

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

<小时/>

问:如何为位图创建 DIB 部分?

A:在LoadImage的最后一个参数中指定LR_CREATEDIBSECTION

说明:

LoadImage((HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE),MAKEINTRESOURCE(ID_IMG_SPAWN), IMAGE_BITMAP,32, 32,NULL)

这是您的LoadImage 函数的代码。请参阅MSDN document of LoadImage ,要创建 DIB 部分,您只需在 LoadImage 的最后一个参数中指定 LR_CREATEDIBSECTION 即可。

<小时/>

问:如何获得预乘 alpha 的 BMP?

答:Pixelformer可以帮助您将 Alpha channel 文件转换为预乘 Alpha BMP。

步骤是

  1. 在 Pixelformer 中打开您的图像(任何格式),然后从菜单中选择“导出”

  • 选择 A8:R8:G8: B8 (32bpp) 和预乘 Alpha,然后点击“确定”。
  • 然后你就可以保存你的BMP文件了!将此 BMP 文件导入到 Visual Studio 资源中,替换以前的 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);

    如下所示,效果很好。

    <小时/>

    我上面回答的这些足以解决这个问题。

    有关DIB bitmaps的更多信息和 Premultiplied Alpha ,请参阅链接。

    关于c++ - 如何添加透明 PNG 作为工具栏图标?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58751417/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com