在 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_CREATEWM_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 过滤器?

在 Picasso 图像加载器中加载位图图像会减慢列表视图中的滚动速度

MFC中加载位图

MFC中加载位图

当我在我的 android 应用程序中从图库中加载图像时,为啥位图返回较小的图像?