在 WM_CREATE 中加载多个位图的 C++ Win32 不会加载
Posted
技术标签:
【中文标题】在 WM_CREATE 中加载多个位图的 C++ Win32 不会加载【英文标题】:C++ Win32 loading multiple bitmaps in WM_CREATE won't load 【发布时间】:2019-09-15 14:34:49 【问题描述】:我正在尝试在启动应用程序时加载一些位图。我正在尝试将它们加载到WM_CREATE
,但只有我加载的最后一个位图会保持加载状态。
我可以将图片加载到WM_PAINT
,但有人告诉我最好将它们加载到WM_CREATE
。
//before switch statement
static HBITMAP bitmap1, bitmap2;
case WM_CREATE:
HINSTANCE hInstance = GetModuleHandle(NULL);
bitmap1 = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_BITMAP1),
IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
bitmap2 = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_BITMAP2),
IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
if (!bitmap1 || !bitmap2) MessageBox(NULL, _T("Error while loading images"), _T("Error!"), MB_ICONEXCLAMATION | MB_OK);
case WM_PAINT:
//Draw bitmap...
我希望两个位图都像在 WM_PAINT
中加载时那样加载
编辑:
问题不是我想的。问题是它在我制作的填充区域后面绘制。我仍然不知道如何解决。
//Draw bitmap function
bool DrawBitmap(HBITMAP hBitmap, int posX, int posY, int sizeX, int sizeY)
BITMAP bmp;
HWND hWnd = FindWindow(windowClassName, NULL);
if (!hWnd) return false;
HDC hdc = GetDC(hWnd);
if (!hdc) return false;
HDC hBitmapDC = CreateCompatibleDC(hdc);
if (!hBitmapDC) return false;
GetObject(hBitmap, sizeof(bmp), &bmp);
SelectObject(hBitmapDC, hBitmap);
BitBlt(hdc, posX, posY, sizeX, sizeY, hBitmapDC, 0, 0, SRCCOPY);
DeleteObject(hBitmap);
ReleaseDC(hWnd, hBitmapDC);
ReleaseDC(hWnd, hdc);
return true;
//Before switch
RECT recRect;
STATIC HBITMAP bitmap1;
//case WM_CREATE:
case WM_CREATE:
HINSTANCE hInstance = GetModuleHandle(NULL);
bitmap1 = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_BITMAP1),
IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
if (!bitmap) MessageBox(NULL, _T("Error while loading images"), _T("Error!"), MB_ICONEXCLAMATION | MB_OK);
return 0;
break;
//case WM_PAINT
case WM_PAINT:
DefWindowProc(hwnd, msg, wParam, lParam);
hdc = GetWindowDC(hwnd);
recRect = -1, -1, 50 + 1, 30 + 1 ;
FillRect(hdc, &recRect, (HBRUSH)CreateSolidBrush(RGB(30, 30, 30)));
if (DrawBitmap(bitmap1, 5, 5, 10, 10) == false) MessageBox(NULL, _T("Error while drawing images"), _T("Error!"), MB_ICONEXCLAMATION | MB_OK);
return DefWindowProc(hwnd, msg, wParam, lParam);
return 0;
break;
当我在WM_PAINT
中声明位图时不会出现问题
【问题讨论】:
您应该在每次调用 LoadImage 时调用GetLastError
,而不仅仅是忽略可能发生的错误。见the documentation
但是如果有错误它不应该返回NULL吗?
是的,如果它返回NULL,那么你需要立即调用GetLastError
获取更多信息。您在尝试诊断问题时犯了两个错误 - 1) 您未能调用 GetLastError 来获取更多信息,以及 2) 您对 LoadBitmap 进行了一次调用,而不是检查该调用的返回值,而是再次调用加载位图。如果位图为 NULL,则每次调用都需要进行错误检查和 GetLastError(),不要等到您想测试 null 返回值。
你知道!bitmap1
是一个空检查,对吧?所以你正在检查NULL,但你检查得太晚了。您应该在调用LoadBitmap
后立即检查NULL。您的检查代码不正确。 bitmap1 = LoadBitmap(); if (!bitmap1) DWORD errorVal = GetLastError(); display_error_message_and_error_value;
那么如果bitmap1
不为NULL,那么你使用相同的逻辑加载bitmap2。您不应该先加载每个位图并延迟检查——使用这种逻辑会丢失有关错误加载位图的所有信息。
WM_CREATE
和WM_PAINT
之间真的没有break;
吗?
【参考方案1】:
GetWindowDC
返回整个窗口的 dc,包括非客户区。你通常需要GetDC
。
回复WM_PAINT
时始终使用BeginPaint/EndPaint
并返回0。
CreateSolidBrush
是 GDI 资源泄漏。创建画笔或其他 GDI 对象后,必须销毁这些对象,否则会发生资源泄漏,10,000 次 GDI 泄漏后程序将崩溃。
在你的绘图函数中有DeleteObject(hBitmap)
这将立即破坏位图。但是您可能希望保留位图句柄并仅在程序完成后销毁它。
建议:
bool DrawBitmap(HDC hdc, HBITMAP hBitmap, int posX, int posY, int sizeX, int sizeY)
HDC memdc = CreateCompatibleDC(hdc);
HGDIOBJ oldbmp = SelectObject(memdc, hBitmap);
BitBlt(hdc, posX, posY, sizeX, sizeY, memdc, 0, 0, SRCCOPY);
SelectObject(memdc, oldbmp);
DeleteDC(memdc);
return true;
...
case WM_PAINT:
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
HBRUSH hbrush = CreateSolidBrush(RGB(255, 0, 0));
FillRect(hdc, &ps.rcPaint, hbrush);
DeleteObject(hbrush);
BITMAP bm1;
GetObject(bitmap1, sizeof(bm1), &bm1);
DrawBitmap(hdc, bitmap1, 0, 0, bm1.bmWidth, bm1.bmHeight);
int x = bm1.bmWidth;
int y = bm1.bmHeight;
BITMAP bm2;
GetObject(bitmap2, sizeof(bm2), &bm2);
DrawBitmap(hdc, bitmap2, x, y, bm2.bmWidth, bm2.bmHeight);
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
DeleteObject(bitmap1);
DeleteObject(bitmap2);
PostQuitMessage(0);
return 0;
【讨论】:
以上是关于在 WM_CREATE 中加载多个位图的 C++ Win32 不会加载的主要内容,如果未能解决你的问题,请参考以下文章
从/在一个目录中加载/保存多个图像 - opencv c++
如何从资源位图文件中加载图像数据以进行 directshow 过滤器?