c++ - Win32 无法添加具有透明度的自定义工具栏图标

标签 c++ winapi bmp hwnd imagelist

我正在使用此代码通过一个具有自定义图像的按钮向窗口添加工具栏:

HWND hToolbar = CreateWindow(TOOLBARCLASSNAME, NULL,WS_CHILD | 
         TBSTYLE_FLAT|TBSTYLE_AUTOSIZE |TBSTYLE_LIST|CCS_BOTTOM, 0, 0, 0, 0,
         hwnd, NULL, ghInstance, NULL); //create the toolbar

SendMessage(hToolbar, WM_SETFONT, (WPARAM)hFontBold, 
      static_cast<LPARAM>(MAKELONG(TRUE, 0))); //set the font. there cannot be the problem

//↓↓↓↓↓**ILC_COLOR32 is specificied here but 32bit bmp is still not showing**//
auto hImagelist = ImageList_Create(32, 32,ILC_COLOR32|ILC_MASK,1, 0);
//↑↑↑↑↑**ILC_COLOR32 is specificied here but 32bit bmp is still not showing**//

HBITMAP bitmap = static_cast<HBITMAP>(ghInstance,
          MAKEINTRESOURCE(ID_IMG_SPAWN),// <- ID_IMG_SPAWN is my custom resource
          IMAGE_BITMAP, 32, 32, NULL));

ImageList_Add(hImagelist, bitmap, nullptr);
SendMessage(hToolbar, TB_SETIMAGELIST,static_cast<WPARAM>(0),(LPARAM)hImagelist);

在上面的代码中,ID_IMG_SPAWN 是我导入到Visual Studio 中的资源bmp 图片。但是,Visual Studio 抛出一个错误,说它无法识别我的 bmp,并且 bmp 在运行应用程序时显示为空白。


Visual Studio 告诉我无法识别我的 bmp,请参阅以下错误:

VS error message


应用程序运行时如下所示:


我了解到 Visual Studio 仅识别 24 位 bmp。

因此,我将 bmp 转换为 24 位并再次导入,将 ILC_COLOR32 更改为 ILC_COLOR24,这确实有效。没有错误,按钮上显示了我的图像。

但是,我丢失了 alpha channel 。因为 24 位位图不支持 alpha channel ,所以我的图像最终有一个丑陋的方形背景。

最佳答案

尝试这样的事情(注意我使用了 "BINARY" 资源..也许它也适用于其他人但不确定..此代码适用于 32 位位图,alpha 透明 PNG , 和 JPEG):

#include <windows.h>
#include <gdiplus.h>

HBITMAP LoadBitmapFromResource(DWORD ResourceID, bool transparent = true)
{
    HANDLE hGlobal = NULL;
    ULONG_PTR GDIToken = 0;
    Gdiplus::Image* Img = NULL;
    Gdiplus::GdiplusStartupInput GDIStartInput = NULL;


    Gdiplus::GdiplusStartup(&GDIToken, &GDIStartInput, NULL);

    HRSRC hResource = FindResource(NULL, MAKEINTRESOURCE(ResourceID), "BINARY");
    if (!hResource) {return NULL;}

    HGLOBAL hFileResource = LoadResource(NULL, hResource);
    if (!hFileResource) {return NULL;}

    LPVOID lpFile = LockResource(hFileResource);
    if (!lpFile) {return NULL;}

    DWORD dwSize = SizeofResource(NULL, hResource);
    if (!dwSize) {return NULL;}

    void* data = LockResource(hFileResource);
    if (!data) {return NULL;}

    IStream* pStream = NULL;
    hGlobal = GlobalAlloc(GMEM_FIXED, dwSize);

    memcpy(hGlobal, data, dwSize);
    UnlockResource(hFileResource);
    FreeResource(hFileResource);

    if (CreateStreamOnHGlobal(hGlobal, true, &pStream) == S_OK)
    {
        Img = new Gdiplus::Image(pStream, false);
        pStream->Release();
        GlobalFree(hGlobal);
        hGlobal = NULL;

        HBITMAP hBitmap = NULL;
        static_cast<Gdiplus::Bitmap*>(Img)->GetHBITMAP(transparent ? Gdiplus::Color::Transparent : Gdiplus::Color(0, 0, 0), &hBitmap);

        delete Img;
        Gdiplus::GdiplusShutdown(GdiImage::GDIToken);
        GDIStartInput = NULL;
        GDIToken = 0;

        return hBitmap;
    }

    GlobalFree(hGlobal);
    hGlobal = NULL;
    Gdiplus::GdiplusShutdown(GdiImage::GDIToken);
    GDIStartInput = NULL;
    GDIToken = 0;

    return NULL;
}

您必须针对 GDIPlus 进行链接。为您加载的每个图像不断启动和关闭 GDIPlus 不是很好。所以最好将其移动到某个地方。但除此之外,一切都应该正常工作。

没有 GDIPlus 也有其他方法,但这会导致一篇很长的文章..

关于c++ - Win32 无法添加具有透明度的自定义工具栏图标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58749796/

相关文章:

java - 如何在java中将存储在Byte数组中的JPG数据转换为BGR数据

c++ - 用 C++ 制作游戏训练器?

c# - 如何在不使用剪贴板的情况下复制图像?

c++ - DirectShow 获取视频属性

c - 我如何知道何时创建窗口?

jquery - Blueimp jQuery 文件上传rails : BMP image preview issue

一个像素可以分成更小的像素吗?或者是否可以使用 1.54 像素而不是 1 或 2?

c++ - 为什么不能同时定义两个指针?

c++ - 如果不是手动完成,子类是否会继承父类的析构函数?

c++ - 如何将 Delphi Stream 传递给 c/c++ DLL