开发者

Load a png resource into a CBitMap

开发者 https://www.devze.com 2023-01-03 08:07 出处:网络
How do I load a png resource into a CBitMap? When I try this it doesn\'t seem to work: CImage image; image.LoadFromResource(AfxGetInstanceHandle(), IDB_PNG1);

How do I load a png resource into a CBitMap? When I try this it doesn't seem to work:

CImage image;
image.LoadFromResource(AfxGetInstanceHandle(), IDB_PNG1);
bitmap.A开发者_Python百科ttach(image.Detach());

It gives me an error resource type not found. Is there any other way to load a PNG resource?


If you are using VS2008 or newer (MFC Feature Pack) you can use CPngImage which derives from CBitmap and is contained in <afxtoolbarimages.h>. CPngImage is an internal class:

The following classes are used internally in MFC. For completeness, this section describes these internal classes, but they are not intended to be used directly in your code.

If you want to use CPngImage you need to use the resource type "PNG":

#define AFX_PNG_RESOURCE_TYPE  _T("PNG")

Example usage

CPngImage image;
image.Load(IDB_PNG1, nullptr);
bitmap.Attach(image.Detach());


LoadFromResource uses LoadImage internally, it doesn't support PNG last time I tried, despite what the documentation says. You can link with CxImage (look on codeproject) but it's a lot of work for little real benefit.

What I did in the end was forget about PNG, use AlphaConv to convert PNG's into 32-bit Windows bitmaps and use CImage with those. Additional advantage is that you can use them with CBitmapButton etc. in MFC without any transformations.

Another way to hack around it is to extract the resource contents to a temporary file, then use CImage::Load to read it from there. If I'd catch you doing that in one of my code bases I'd punch you in the face though ;)


If you do not really need a CBitmap, but only an handle this may useful for you.

Or if you can get a CBitMap from the HBITMAP this function returns it is also good.

I use this on a commercial application and it works.

// Based on afxbutton.cpp's static function ButtonLoadBitmap
HBITMAP __stdcall ButtonLoadBitmap(UINT uiBmpResId)
{
    if (uiBmpResId == 0)
    {
        return NULL;
    }

    LPCTSTR lpszResourceName = MAKEINTRESOURCE(uiBmpResId);
    ENSURE(lpszResourceName != NULL);

    HBITMAP hbmp = NULL;

    // Try to load PNG image first:
    CPngImage pngImage;
    if (pngImage.Load(lpszResourceName))
    {
        hbmp = (HBITMAP) pngImage.Detach();
    }
    else
    {
        HINSTANCE hinstRes = AfxFindResourceHandle(lpszResourceName, RT_BITMAP);
        if (hinstRes == NULL)
        {
            return NULL;
        }

        UINT uiLoadImageFlags = LR_CREATEDIBSECTION | LR_LOADMAP3DCOLORS;

        hbmp = (HBITMAP) ::LoadImage(hinstRes, lpszResourceName, IMAGE_BITMAP, 0, 0, uiLoadImageFlags);
    }

    return hbmp;
}


Use a library like CxImage (http://www.xdp.it/cximage.htm) to do all the heavy lifting for you. The code becomes as simple as :-

CxImage image;
if (image.LoadResource(<resource_instance_handle>, <resource_id>, CXIMAGETYPE_PNG))
{
    HBITMAP hbmp = image.CreateHBITMAP();
    ... do something with hbmp ...
}

(note that I'm writing this code from memory -- you may need to tweak it slightly to get it to work!)

I use CxImage a lot for the graphics in my programs and it simplifies things tremendously.

0

精彩评论

暂无评论...
验证码 换一张
取 消