从内存缓冲区创建HBITMAP

AJG*_*G85 11 c++ mfc gdi bitmap hbitmap

我有一个应用程序,它从数据库中加载一些blob数据,可以表示各种位图和图标的png格式或原始二进制数据.这是存储在std::vector<unsigned char>

我正在使用CImageList对象在树视图,工具栏图像等中显示各种图像,但问题是从内存中的数据创建位图会变得模糊,好像它在执行如下操作时缺少像素:

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

为了解决这个问题,我现在只需将向量中的data()写入临时文件,然后使用LoadImage将其读回并从中创建HBITMAP.这是完美的,但无可否认,这是一个无耻的黑客,我希望完全没必要.

我在网上环顾四周,但没有找到任何关于如何"正确"从内存创建hbitmaps的好例子.我希望能够创建这些位图,以便添加到图像列表中,而无需任何文件i/o和有限数量的复制数据(如果可能).

寻找最好的方法来做到这一点,显然Windows特定的代码是好的.

更新:

根据jdv的回答,我开始使用CreateCompatibleBitmap,CreateDIBitmap,最后是CreateDIBSection.所有这些最终创建了可爱的黑色位图,而不是之前的模糊位图,所以我必须再次做错了我的猜测是因为这个位图创建是在一个没有屏幕直流或窗口概念的对象中完成的,使用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);
Run Code Online (Sandbox Code Playgroud)

我现在当然认为必须有一个更简单的方法来解决这个问题,或许完全避免使用HBITMAP并直接与CBitmap班级合作?当它归结为将图像添加到CImageList我正在使用CBitmap::FromHandle(HBITMAP hbitmap, COLORREF mask)的时候.有谁知道CBitmap从一个初始化对象的简单方法std::vector<unsigned char>

小智 5

我使用CreateCompatibleBitmap,然后打电话SetDIBits给你填写你的数据.这些是我见过的功能,而且SetDIBits非常灵活,虽然冗长.

在我的MFC年代,CreateBitmap由于涉嫌性能问题而被避免.

  • 我现在正在查看 CreateDIBitmap,据我所知,它基本上创建了一个 DC 兼容位图,然后如果您指定 CBM_INIT 标志,则调用等效的 SetDIBits。谁在windows API中命名参数和structs的成员需要被枪毙。 (2认同)

AJG*_*G85 3

使用 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();
}
Run Code Online (Sandbox Code Playgroud)

编辑:根据 Jegatheesh 更改

  • 如何从`Gdiplus::Bitmap*`获取HBITMAP? (3认同)