Winapi 从加载到内存中的24位BMP文件中获取HBITMAP

Winapi 从加载到内存中的24位BMP文件中获取HBITMAP,winapi,bitmap,Winapi,Bitmap,我有一个24位BMP文件加载到RAM中,我正在尝试为这个图像文件创建一个HBITMAP。我找到了一些我一直在尝试的例子,但似乎无法奏效。基本上,我需要一个文件的HBITMAP,这样我就可以卸载文件并保留HBITMAP,以后可以用DeleteObject()处理它。由于此位图在我的应用程序中很早就加载了,所以没有应用程序窗口,因此没有HDC。这就是我到目前为止所做的:- HBITMAP cBitmap; // This should be where my bitmap handle ends

我有一个24位BMP文件加载到RAM中,我正在尝试为这个图像文件创建一个HBITMAP。我找到了一些我一直在尝试的例子,但似乎无法奏效。基本上,我需要一个文件的HBITMAP,这样我就可以卸载文件并保留HBITMAP,以后可以用DeleteObject()处理它。由于此位图在我的应用程序中很早就加载了,所以没有应用程序窗口,因此没有HDC。这就是我到目前为止所做的:-

HBITMAP cBitmap;  // This should be where my bitmap handle ends up.
mem;              // This is a void* pointer to the loaded BMP file


tagBITMAPFILEHEADER bfh = *(tagBITMAPFILEHEADER*)mem;
tagBITMAPINFOHEADER bih = *(tagBITMAPINFOHEADER*)(mem + sizeof(tagBITMAPFILEHEADER));
RGBQUAD rgb = *(RGBQUAD*)(mem + sizeof(tagBITMAPFILEHEADER) + sizeof(tagBITMAPINFOHEADER));

BITMAPINFO bi;
bi.bmiColors[0] = rgb;
bi.bmiHeader = bih;

UINT8* pixels = mem + bfh.bfOffBits;
void* ppv;
HBITMAP hBitmap = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, &ppv, NULL, 0);
SetDIBits(NULL, hBitmap, 0, bih.biHeight, pixels, &bi, DIB_RGB_COLORS);
GetObject(hBitmap, sizeof(BITMAP), &cBitmap);

出于某种让我困惑的原因,cBitmap最终为空。还有一件事让我困惑。。。DIB_RGB_颜色意味着BITMAPINFO有一个指向文字RGB值的指针,但是对于没有调色板的24位图像,它是如何工作的呢?

如果您是从磁盘加载文件,那么使用
LR_LOADFROMFILE
标志的
LoadImage()
可能是最简单的方法

要从已加载到内存中的文件数据创建
HBITMAP
,可以执行以下类似操作:

HBITMAP ConvertDibToHBitmap(void* bmpData)
{
    HBITMAP hBitmap = NULL;
    BOOL success = FALSE;

    // NOTE: Assumes the BITMAPFILEHEADER is present (not normally the case for
    // an in-memory DIB)
    LPBITMAPFILEHEADER bfh = (LPBITMAPFILEHEADER) bmpData;
    LPBITMAPINFOHEADER bih = (LPBITMAPINFOHEADER) (bfh + 1);
    void *pixels = (char*) (bih + 1); // NOTE: Assumes no color table (i.e., bpp >= 24)

    HDC hdc = GetDC(NULL);
    if (hdc != NULL) {
        hBitmap = CreateCompatibleBitmap(hdc, bih->biWidth, bih->biHeight);
        if (hBitmap != NULL) {
            HDC hdcMem = CreateCompatibleDC(hdc);
            if (hdcMem != NULL) {
                HBITMAP hOldBitmap = (HBITMAP)SelectObject(hdcMem, hBitmap);
                if (StretchDIBits(hdcMem, 0, 0, bih->biWidth, bih->biHeight,
                        0, 0, bih->biWidth, bih->biHeight, pixels,
                        (LPBITMAPINFO) bih, DIB_RGB_COLORS, SRCCOPY) > 0)
                    success = TRUE;

                SelectObject(hdcMem, hOldBitmap);
                DeleteDC(hdcMem);
            }
        }

        ReleaseDC(NULL, hdc);
    }

    if (!success && hBitmap != NULL) {
        DeleteObject(hBitmap);
        hBitmap = NULL;
    }

    return hBitmap;
}

嗯,
GetObject
不是这样工作的。用法是

GetObject(handle, sizeof(object), &object);
在您的情况下,期望是您将其称为

BITMAP bitmap;
GetObject(hBitmap, sizeof(BITMAP), &bitmap);
您没有将指针传递给
位图
结构,因此行为未定义

您根本不需要
GetObject
。您已经有了
HBITMAP
。它位于
hBitmap
变量中

cBitmap = hBitmap;

你好谢谢你的回答,但你一定错过了我问题中的一些要点。首先,位图已加载到内存中,无法使用LoadImage/LoadBitmap()加载,因为它是嵌入在二进制数据块中的.bmp文件。我从这个二进制数据块中提取.bmp文件,并需要从中创建一个HBITMAP。其次,正如我所说的,创建HBITMAP是在我的应用程序启动的很早就完成的,所以没有窗口或HDC,所以不能使用GetDC()之类的东西,因为此时没有应用程序窗口。如果
LoadImage()
在您的情况下不起作用,则使用第二种方法。即使没有应用程序窗口,也可以使用
GetDC(NULL)
获取屏幕的设备上下文(实际上是桌面窗口)。所以,这对你的案子来说应该很好。