CreateBitmap 图像未在 window 上打印

CreateBitmap image is not printing on window

我需要从文件加载 bmp 图像并将图像数据加载到缓冲区,然后从中创建新图像。 (我这样做是有原因的)。我写了一个示例程序来模拟我的项目场景。

     LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
     static BITMAP  bm;
     static HBITMAP bmpSource = NULL;
     static HBITMAP hbmp=NULL;
     static HDC hdcSource = NULL;
     static HDC hdcDestination= NULL;
     static PAINTSTRUCT ps;
     BITMAPINFO bitmap_info[2] = {0};

      if (Msg == WM_CREATE) {
       bmpSource = (HBITMAP)LoadImage(NULL, L"bmp00004.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );

       GetObject(bmpSource, sizeof(BITMAP), &bm);  

       bitmap_info->bmiHeader.biSize = sizeof(bitmap_info->bmiHeader);
       int ret = GetDIBits(hdcSource, bmpSource, 0, bm.bmHeight, NULL, bitmap_info,DIB_RGB_COLORS);

       LPVOID *lpvBits = (LPVOID*) malloc(3*(bm.bmWidth * bm.bmHeight * sizeof(DWORD)));
       int gotData = GetDIBits(hdcSource, bmpSource, 0,bm.bmHeight,lpvBits, bitmap_info, DIB_RGB_COLORS);

       hbmp = (HBITMAP) CreateBitmap(bm.bmWidth, bm.bmHeight, bm.bmPlanes, bm.bmBitsPixel ,lpvBits);
        hdcSource = CreateCompatibleDC(GetDC(0));
        SelectObject(hdcSource, hbmp);
       return 0;

     }else if (Msg == WM_PAINT) {
       hdcDestination = BeginPaint(hWnd, &ps); 
       BitBlt(hdcDestination, 0, 0,bm.bmWidth , bm.bmHeight, hdcSource, 0, 0, SRCCOPY);

        EndPaint(hWnd, &ps);
       return 0;
     }else if (Msg == WM_DESTROY) {
        DeleteDC(hdcSource);
        EndPaint(hWnd, &ps);
        DeleteObject(bmpSource);
        DeleteObject(hbmp);
     }
     return DefWindowProc(hWnd, Msg, wParam, lParam); 
}

我期待程序在 window 上打印图像。 现在新创建的图像不显示在 window 上。我只能看到一个灰色框。

您的代码可以大大简化。没有必要调用 GetDIBits(你在设置 hdcSource 之前正在做的),你应该正确清理并尽量减少静态变量的使用。类似于以下内容(为清楚起见省略了错误检查):

LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    static HBITMAP bmpSource;

    if (Msg == WM_CREATE) {
        bmpSource = (HBITMAP)LoadImage(NULL, L"bmp00004.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
        return 0;
    }

    if (Msg == WM_PAINT) {
        PAINTSTRUCT ps;
        HDC hdcDestination = BeginPaint(hWnd, &ps); 
        BITMAP bm;
        GetObject(bmpSource, sizeof(bm), &bm);  
        HDC hdcSource = CreateCompatibleDC(hdcDestination);
        HGDIOBJ hOldBmp = SelectObject(hdcSource, bmpSource);

        BitBlt(hdcDestination, 0, 0,bm.bmWidth , bm.bmHeight, hdcSource, 0, 0, SRCCOPY);

        SelectObject(hdcSource, hOldBmp);
        DeleteDC(hdcSource);
        EndPaint(hWnd, &ps);
        return 0;
    }

     if (Msg == WM_DESTROY)
          DeleteObject(bmpSource);

     return DefWindowProc(hWnd, Msg, wParam, lParam); 
}

您似乎正试图读取位图文件并写入另一个 HBITMAP 句柄,无论出于何种原因...

LoadImage returns 兼容位图(除非您指定 LR_CREATEDIBSECTION),因此您需要 CreateCompatibleBitmap 后跟 SetDIBits 来复制该源位图。

出于某种原因,您已经声明了 BITMAPINFO bminfo[2] 但您只需要一个 bminfo 对象。您需要 newmalloc 为一个对象分配足够的内存。请注意,您不能随机交换指针数组,反之亦然。如果您使用调试器,您会注意到函数失败并且 bminfo 未正确填充。

如果您自己设置 BITMAPINFOHEADER 比让 GetDIBits 填充该参数更容易:

LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    static HDC hdc_memory;
    static HBITMAP hbmp_src;
    static HBITMAP hbmp_dst;
    static BITMAP bm;

    if(Msg == WM_CREATE) 
    {
        hbmp_src = (HBITMAP)LoadImage(NULL, L"file.bmp", 
                    IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

        HDC hdc = GetDC(0);
        hdc_memory = CreateCompatibleDC(hdc);

        GetObject(hbmp_src, sizeof(bm), &bm);
        int w = bm.bmWidth;
        int h = bm.bmHeight;
        if(h < 0) h = -h;
        int size = ((w * bm.bmBitsPixel + 31) / 32) * 4 * h;
        BITMAPINFOHEADER bi = { sizeof(bi), w, h, bm.bmPlanes, bm.bmBitsPixel };
        BYTE* bits = new BYTE[size];

        GetDIBits(hdc, hbmp_src, 0, h, bits, (BITMAPINFO*)&bi, DIB_RGB_COLORS);
        //change the pixel data in bits if that's your goal ...
        hbmp_dst = CreateCompatibleBitmap(hdc, w, h);
        SetDIBits(hdc, hbmp_dst, 0, h, bits, (BITMAPINFO*)&bi, DIB_RGB_COLORS);
        SelectObject(hdc_memory, hbmp_dst);

        delete[] bits;
        ReleaseDC(0, hdc);
        return 0;
    }
    else if(Msg == WM_PAINT) 
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);
        BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdc_memory, 0, 0, SRCCOPY);
        EndPaint(hWnd, &ps);
        return 0;
    }
    else if(Msg == WM_DESTROY) 
    {
        DeleteDC(hdc_memory);
        DeleteObject(hbmp_src);
        DeleteObject(hbmp_dst);
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hWnd, Msg, wParam, lParam);
}