2

I am using this code to add a toolbar to the window with one button having a custom image:

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);

In the code above, ID_IMG_SPAWN is the resource bmp image I imported to Visual Studio. However, Visual Studio threw an error saying it didn't recognize my bmp, and the bmp showed up blank when running the application.


Visual Studio told me my bmp wasn't recognized, see the below error:

VS error message


When the app runs it looks as below:


I learned that Visual Studio hereby recognizes ONLY 24bit bmp.

So, I converted the bmp to 24bit and imported it again, changed ILC_COLOR32 to ILC_COLOR24, that really worked. No error and my image were shown on the button.

However, I lost my alpha channel. Because 24bit bitmap does not support an alpha channel, my image ended up having an ugly square background.

  • Can you upload the 32-bit image? I have never had a problem using a 32-bit bitmap as a control background I WinAPI. Have you tried GDIPlus to load it? – Brandon Nov 07 '19 at 13:46
  • @Brandon https://drive.google.com/open?id=1w2BUSUA9h31FbpvZFWmBbVaIfViefsoN here is the image. also i am not using it as background: i need the alpha channel reserved –  Nov 07 '19 at 13:50
  • Please dial down on the usage of **bold** formatting. This adds a lot of pixels to each letter, making the text more difficult to read. In your post, I found no reason to use it, thus I removed it. Please only use it for things as paragraph headings in very long posts, or the 0.001% of words which cannot be emphasised properly through restructuring the surrounding sentence. Usually it just puts people off, resulting in downvotes and/or less answers. – Adriaan Nov 08 '19 at 10:06
  • The question already has an answer here https://stackoverflow.com/questions/58751417/how-can-i-add-a-transparent-png-as-a-toolbar-icon –  Nov 09 '19 at 04:59

3 Answers3

1

Try something like this (Note I used a "BINARY" resource.. maybe it will work with others too but not sure.. This code works with 32-bit bitmaps, alpha-transparent PNGs, and 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;
}

You will have to link against GDIPlus. It's not very nice to constantly startup and shutdown GDIPlus for every image you load.. so it's best to move that somewhere.. but other than that, everything should work just fine.

There are other ways without GDIPlus but it makes for a long post..

Brandon
  • 22,723
  • 11
  • 93
  • 186
  • Sorry but, is gdi+ supported ordinarily by win7 system? If it is, everything is fine. I want the application to run on even a new win7 system without any framework installed later. –  Nov 08 '19 at 03:05
  • @AkutaHinako yes its there in windows7. Just try it. – Brandon Nov 08 '19 at 04:39
1

I learned that Visual Studio hereby recognizes ONLY 24bit bmp.

No, that's wrong. Visual Studio supports alpha-premultiplied 32-bit bitmaps.

32-bit bitmap has 8 bits for ALPHA, it's capable to make a smooth effect.


To show a 32-bit bitmap properly, you have to:

  • specify ILC_COLOR32

  • change the resource of ID_IMG_SPAWN to a 32-bit bitmap with premultiplied alpha.

  • create a DIB section to your bitmap when loading

(Win32's format requirement is very strict)


Q: How to create a DIB section to the bitmap?

A: Specify LR_CREATEDIBSECTION in the last parameter of LoadImage.

Explanation:

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

This is your code of the LoadImage function. See the MSDN document of LoadImage, to create the DIB section, all you need is to specify LR_CREATEDIBSECTION in the last parameter of LoadImage.


Q: How to get a BMP with premultiplied alpha?

A: Pixelformer can help you convert your alpha-channeled file to a premultiplied-alpha BMP.

The steps are

  1. Open your image (any format) in Pixelformer and choose Export from the menu

  1. Select A8:R8:G8: B8 (32bpp) and Premultiplied Alpha, then click Ok.

Then you can save your BMP file! Import this BMP file to Visual Studio resources, replacing your previous 24-bit BMP.


Then, you don't need to use the ImageList_AddMasked (which makes the image sharp) anymore, because you already have a recognizable ALPHA in your 32-bit BMP. So, straight use ImageList_Add.

Okay, after the manipulations explained above your code should be this:

// 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);

This worked fine as below.


These I answered above is well enough to solve this problem. You may wonder "What means DIB bitmaps?" "What is Premultiplied Alpha?". Those are the deep topics.

To learn DIB bitmaps and Premultiplied Alpha, see the links.

-1

If you are using Visual Studio 2010 or higher (i guess), you can use PNG files. As stated here.

Filip
  • 155
  • 10
  • 1
    It appears that you don't understand the question and have Googled "visual studio png" and pasted the first link. Note that this link has no relation to the question, and that link-only answers are discouraged. – CodeCaster Nov 08 '19 at 06:34