C++ 从内存缓冲区创建 HBITMAP
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4598872/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Creating HBITMAP from memory buffer
提问by AJG85
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>
我有一个应用程序,它从数据库中加载一些 blob 数据,该数据库可以表示各种位图和图标的 png 格式或原始二进制数据。这被存储在一个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:
我正在使用CImageList
对象在树视图、工具栏图像等中显示各种图像,但问题是从内存中的数据创建位图变得模糊,好像在执行以下操作时缺少像素:
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.
为了暂时解决这个问题,我只是将向量中的 data() 写入临时文件,然后使用 LoadImage 将其读回并从中创建 HBITMAP。这非常有效,但是这无疑是一种无耻的黑客行为,我希望完全没有必要。
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.
我在网上环顾四周,但没有找到任何关于如何从内存“正确”创建 hbitmaps 的很好的例子。如果可能的话,我希望能够创建这些位图以添加到图像列表中,而无需任何文件 i/o 和有限数量的数据复制。
Looking for the best way to do this and obviously windows specific code is fine.
寻找最好的方法来做到这一点,显然 Windows 特定的代码很好。
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:
根据 jdv 的回答,我开始使用 CreateCompatibleBitmap、CreateDIBitmap,最后是 CreateDIBSection。所有这些最终都创建了可爱的黑色位图而不是之前的模糊位图,所以我一定又做错了,我的猜测是因为这个位图创建是在一个没有屏幕 dc 或窗口概念的对象中完成的,使用GetDC(NULL)
和CreateCompatibleDC(NULL)
都不好。示例代码:
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>
?
我现在当然认为必须有一种更简单的方法来解决这个问题,也许是完全避免使用 HBITMAP 并直接与CBitmap
类一起工作?当归结为将图像添加到CImageList
我正在使用的图像时CBitmap::FromHandle(HBITMAP hbitmap, COLORREF mask)
。有谁知道CBitmap
从 a初始化对象的简单方法std::vector<unsigned char>
?
采纳答案by AJG85
Using GdiPlus I got something that works pretty well and doesn't involve pulling any teeth!
使用 GdiPlus 我得到了一些效果很好的东西,不需要拔牙!
Gdiplus::Bitmap* pBitmap = NULL;
IStream* pStream = NULL;
HRESULT hResult = ::CreateStreamOnHGlobal( NULL, TRUE, &pStream );
if(hResult == S_OK && pStream)
{
hResult = pStream->Write(&bits[0], ULONG(bits.size()), NULL);
if(hResult == S_OK)
pBitmap = Gdiplus::Bitmap::FromStream(pStream);
pStream->Release();
}
Edit:Changed per Jegatheesh
编辑:根据 Jegatheesh 更改
回答by AJG85
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.
我会使用CreateCompatibleBitmap
, 然后打电话SetDIBits
用你的数据填充它。这些是我见过的功能,SetDIBits 非常灵活,虽然冗长。
In my MFC years, CreateBitmap
was avoided due to suspected performance issues.
在我的 MFC 年,CreateBitmap
由于怀疑性能问题而被避免。