1
votes

Win32 Impossible d'ajouter une icône de barre d'outils personnalisée ayant une transparence

J'utilise ce code pour ajouter une barre d'outils à la fenêtre avec un bouton ayant une image personnalisée:

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

Dans le code ci-dessus, ID_IMG_SPAWN est la ressource image bmp que j'ai importée dans Visual Studio. Cependant, Visual Studio a généré une erreur disant qu'il ne reconnaissait pas mon bmp et que le bmp était vide lors de l'exécution de l'application.


Visual Studio m'a dit que mon bmp n'était pas reconnu, voir le ci-dessous l'erreur:

 VS error message


Lorsque l'application s'exécute, elle ressemble à ceci:


J'ai appris que Visual Studio ne reconnaît que les bmp 24 bits par la présente.

J'ai donc converti le bmp en 24 bits et l'ai réimporté, modifié ILC_COLOR32 à ILC_COLOR24 , cela a vraiment fonctionné. Aucune erreur et mon image n'a été affichée sur le bouton.

Cependant, j'ai perdu mon canal alpha. Étant donné que le bitmap 24 bits ne prend pas en charge un canal alpha, mon image a fini par avoir un arrière-plan carré laid.


4 commentaires

Pouvez-vous télécharger l'image 32 bits? Je n'ai jamais eu de problème en utilisant un bitmap 32 bits comme arrière-plan de contrôle I WinAPI. Avez-vous essayé GDIPlus pour le charger?


@Brandon drive.google.com/open?id=1w2BUSUA9h31FbpvZFWm l'image est ici . aussi je ne l'utilise pas comme arrière-plan: j'ai besoin du canal alpha réservé


Veuillez sélectionner l'utilisation du formatage gras . Cela ajoute beaucoup de pixels à chaque lettre, ce qui rend le texte plus difficile à lire. Dans votre message, je n'ai trouvé aucune raison de l'utiliser, donc je l'ai supprimé. Veuillez ne l'utiliser que pour des choses comme en-têtes de paragraphe dans des articles très longs, ou pour les 0,001% de mots qui ne peuvent pas être mis en valeur correctement en restructurant la phrase environnante. Habituellement, cela décourage les gens, ce qui entraîne des votes négatifs et / ou moins de réponses.


La question a déjà une réponse ici stackoverflow.com/questions/58751417/...


3 Réponses :


-1
votes

Si vous utilisez Visual Studio 2010 ou une version ultérieure (je suppose), vous pouvez utiliser des fichiers PNG. Comme indiqué ici .


1 commentaires

Il semble que vous ne compreniez pas la question et que vous ayez googlé "visual studio png" et collé le premier lien. Notez que ce lien n'a aucun rapport avec la question et que les réponses par lien uniquement sont déconseillées.



1
votes

Essayez quelque chose comme ceci (notez que j'ai utilisé une ressource "BINARY" .. peut-être que cela fonctionnera aussi avec d'autres mais pas sûr. Ce code fonctionne avec des bitmaps 32 bits, des PNG alpha-transparents , et 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;
}

Vous devrez créer un lien avec GDIPlus . Ce n'est pas très agréable de démarrer et d'arrêter constamment GDIPlus pour chaque image que vous chargez .. il est donc préférable de déplacer cela quelque part .. mais à part ça, tout devrait bien fonctionner.

Il existe d'autres moyens sans GDIPlus mais cela fait un long post ..


2 commentaires

Désolé, mais gdi + est-il généralement pris en charge par le système win7? Si c'est le cas, tout va bien. Je veux que l'application fonctionne même sur un nouveau système win7 sans aucun cadre installé plus tard.


@AkutaHinako oui c'est là dans windows7. Essayez-le.



0
votes

J'ai appris que Visual Studio reconnaît par la présente UNIQUEMENT les bmp 24 bits.

Non, c'est faux. Visual Studio prend en charge les bitmaps 32 bits prémultipliés alpha .

Le bitmap 32 bits a 8 bits pour ALPHA, il est capable de créer un effet fluide.


Pour afficher correctement une image bitmap 32 bits, vous devez:

  • spécifiez ILC_COLOR32

  • changez la ressource de ID_IMG_SPAWN en un bitmap 32 bits avec alpha prémultiplié .

  • créer une section DIB dans votre bitmap lors du chargement

(le format requis par Win32 est très strict)


Q: Comment créer une section DIB dans le bitmap?

A: Spécifiez LR_CREATEDIBSECTION dans le dernier paramètre de LoadImage.

Explication:

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

Ceci est votre code de la fonction LoadImage . Consultez le document MSDN de LoadImage , pour créer la section DIB, il vous suffit de spécifier LR_CREATEDIBSECTION dans le dernier paramètre de LoadImage.


Q: Comment obtenir un BMP avec alpha prémultiplié?

R: Pixelformer peut vous aider à convertir votre fichier à canal alpha vers un BMP alpha prémultiplié.

Les étapes sont

  1. Ouvrez votre image (n'importe quel format) dans Pixelformer et choisissez Exporter dans le menu

  1. Sélectionnez A8: R8: G8: B8 (32 bpp) et Alpha prémultiplié , puis cliquez sur OK.

Ensuite, vous pouvez enregistrer votre fichier BMP! Importez ce fichier BMP dans les ressources Visual Studio, en remplaçant votre précédent BMP 24 bits.


Ensuite, vous n'avez pas besoin d'utiliser le ImageList_AddMasked (qui rend l'image sharp), car vous avez déjà un ALPHA reconnaissable dans votre BMP 32 bits. Donc, utilisez directement ImageList_Add.

D'accord, après les manipulations expliquées ci-dessus, votre code devrait être le suivant:

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

Cela a fonctionné très bien comme ci-dessous.


Ce que j'ai répondu ci-dessus est assez bien pour résoudre ce problème. Vous vous demandez peut-être "Que signifie les bitmaps DIB?" "Quel est Alpha Prémultiplié?". Ce sont les sujets profonds.

Pour en savoir bitmaps DIB et Alpha prémultiplié , voir les liens .


0 commentaires