Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
520 views
in Technique[技术] by (71.8m points)

c++ - Creating HBITMAP from memory buffer

I have an application which loads some blob data out of a database which can represent png formatted or raw binary data for various bitmaps and icons. This is being stored in a std::vector<unsigned char>

I'm using CImageList objects to display various images in tree views, toolbar images, etc but the problem is creating bitmaps from the data in memory are coming out fuzzy as if it's missing pixels when doing something like below:

std::vector<unsigned char> bits;
HBITMAP hbitmap = CreateBitmap(16, 16, 1, 32, bits.data());

To work around this issue for now I am simply writing out the data() in the vector to a temporary file and then using LoadImage to read it back in and creating the HBITMAP from that. This works perfectly however that is admittedly a shameless hack and should be completely unnecessary I would hope.

I've looked around online but haven't found any really good examples of how to "properly" create hbitmaps from memory. I would like to be able to create these bitmaps to be added to the image list without any file i/o and limited amounts of copying the data around if possible.

Looking for the best way to do this and obviously windows specific code is fine.

UPDATE:

Based on jdv's answer I began playing with CreateCompatibleBitmap, CreateDIBitmap, and finally CreateDIBSection. All of these ended up creating lovely black bitmaps instead of the previous fuzzy bitmaps so I must be doing something wrong again and my guess is since this bitmap creation is being done in an object that has no concept of the screen dc or window that using GetDC(NULL) and CreateCompatibleDC(NULL) are no good. Sample code:

    BITMAPINFO bmi;
    ZeroMemory(&bmi, sizeof(BITMAPINFO));
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biBitCount = 32;
    bmi.bmiHeader.biHeight = 16;
    bmi.bmiHeader.biWidth = 16;
    bmi.bmiHeader.biPlanes = 1;

    HDC dc = CreateCompatibleDC(NULL);
    HBITMAP hbitmap = CreateDIBSection(dc, &bmi, DIB_RGB_COLORS, (void**)blobData.GetMember<FILEDATAFIELD_DATA>().data(), NULL, 0);

I am now of course thinking there has got to be a simpler way to go about this perhaps by avoiding the HBITMAP altogether and working directly with CBitmap class? When it comes down to adding the image to the CImageList I'm using CBitmap::FromHandle(HBITMAP hbitmap, COLORREF mask) anyway. Does anyone know a simple way to initialize a CBitmap object from a std::vector<unsigned char>?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I'd use CreateCompatibleBitmap, and then call SetDIBits to fill it with your data. These are functions I have seen to work, and SetDIBits is quite flexible, although verbose.

In my MFC years, CreateBitmap was avoided due to suspected performance issues.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...