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

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

HWND hToolbar = CreateWindow(TOOLBARCLASsnAME,NULL,WS_CHILD | 
         TBSTYLE_flaT|TBSTYLE_AUTOSIZE |TBSTYLE_LIST|CCS_BOTTOM,hwnd,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,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无法识别,请参见以下错误:

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


应用运行时,外观如下:

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


我了解到Visual Studio特此只能识别24位bmp。

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

但是,我丢失了我的Alpha频道。由于24位位图不支持alpha通道,因此我的图像最终变成了难看的正方形背景。

xy13659822798 回答:Win32无法添加具有透明度的自定义工具栏图标

尝试这样的事情(请注意,我使用了"BINARY"资源。也许它也可以与其他人一起使用,但不确定。此代码适用于32位位图,透明的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),&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的方法,但是它可以发表很长的篇幅。

,
  

我了解到Visual Studio特此只能识别24位bmp。

不,那是错误的。 Visual Studio 支持Alpha预乘的32位位图

32位位图具有8位用于ALPHA,可以产生平滑效果。


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

  • 指定ILC_COLOR32

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

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

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


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

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

说明:

  

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

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


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

A:Pixelformer可以帮助您将Alpha通道文件转换为预乘Alpha BMP。

步骤是

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

  1. 选择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,hwnd,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,ILC_COLOR32 /*DON'T NEED THE MASK. CHANGED TO ILC_COLOR32.*/,1,0);

HBITMAP bitmap = static_cast<HBITMAP>(LoadImage((HINSTANCE)GetWindowLong(hwnd,LR_CREATEDIBSECTION  /*THIS IS IMPORTANT*/   ));

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

如下所示,效果很好。


我在上面回答的这些足以解决此问题。您可能想知道“什么是DIB位图?” “什么是预乘Alpha?”。这些是很深的话题。

要学习DIB bitmapsPremultiplied Alpha,请参阅链接。

,

如果您使用的是Visual Studio 2010或更高版本(我想),则可以使用PNG文件。如here所述。

本文链接:https://www.f2er.com/3144483.html

大家都在问