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
对象。您需要 new
或 malloc
为一个对象分配足够的内存。请注意,您不能随机交换指针数组,反之亦然。如果您使用调试器,您会注意到函数失败并且 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);
}
我需要从文件加载 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
对象。您需要 new
或 malloc
为一个对象分配足够的内存。请注意,您不能随机交换指针数组,反之亦然。如果您使用调试器,您会注意到函数失败并且 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);
}