C++ 停止显示位图

C++ Stop displaying bitmap

本文关键字:位图 显示 C++      更新时间:2023-10-16

如何在 Win32 项目中停止显示位图。我有一个WM_PAINT调用的方法,称为LoadBitmap。它的代码如下所示:

bool LoadBitmap(LPTSTR szfilename, HDC winhdc, int x, int y) {
    HBITMAP bitmap;
    bitmap = (HBITMAP)LoadImage(NULL, szfilename, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    if (bitmap == NULL) {
        ::MessageBox(NULL, _T("Bitmap failed"), NULL, MB_OK);
        return false;
    }
    HDC hdc;
    hdc = ::CreateCompatibleDC(winhdc);
    if (hdc == NULL)
    {
        ::MessageBox(NULL, _T("HDC FAILED"), NULL, MB_OK);
        return false;
    }
    BITMAP qbitmap;
    int ireturn = GetObject(reinterpret_cast<HGDIOBJ>(bitmap), sizeof(BITMAP), reinterpret_cast<LPVOID>(&qbitmap));
    if (!ireturn) {
        ::MessageBox(NULL, _T("RETURN FAILED"), NULL, MB_OK);
        return false;
    }
    HBITMAP holdbitmap = (HBITMAP)::SelectObject(hdc, bitmap);
    if (holdbitmap == NULL) {
        ::MessageBox(NULL, _T("HOLD FAILED"), NULL, MB_OK);
        return false;
    }
    BOOL qRetBlit = ::BitBlt(winhdc, x, y, qbitmap.bmWidth, qbitmap.bmHeight, hdc, 0, 0, SRCCOPY);
    if (!qRetBlit)
    {
        ::MessageBox(NULL, _T("BLIT FAILED"), NULL, MB_OK);
        return false;
    }
    ::SelectObject(hdc, holdbitmap);
    ::DeleteDC(hdc);
    ::DeleteObject(bitmap);
    return true;
}

x 和 y 不断变化。但是,当 x 和 y 发生变化时,它们的前一个实例会保留下来。

在位图绘制

到新位置后,如何停止显示位图?

如果有背景画笔,则每次绘制调用都会擦除旧位图。如果没有背景,则手动擦除它,例如使用FillRect这是双缓冲的示例,假设没有背景画笔。

case WM_PAINT:
{
    ...
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hwnd, &ps);
    RECT rc = ps.rcPaint;
    HDC memdc = CreateCompatibleDC(hdc);
    HBITMAP membitmap = CreateCompatibleBitmap(hdc, rc.right, rc.bottom);
    HGDIOBJ oldbitmap = SelectObject(memdc, membitmap);
    //double-buffer ready, do custom paintings here:
    FillRect(memdc, &rc, GetSysColorBrush(COLOR_3DFACE));
    LoadBitmap(filename, memdc, x, y);
    //BitBlt to hdc
    BitBlt(hdc, 0, 0, rc.right, rc.bottom, memdc, 0, 0, SRCCOPY);
    //cleanup:
    SelectObject(hdc, oldbitmap);
    DeleteObject(membitmap);
    DeleteDC(memdc);
    EndPaint(hwnd, &ps);
    return 0;
}

编辑*************

只加载一次位图文件会更快。对于每个绘制请求,我们只需要绘制位图,而不是每次 + 绘制 LoadImage。

您可以在窗口的过程中将HBITMAP句柄声明为静态值。WM_CREATE设置一次,WM_NCDESTROY清理一次。现在我们可以在侧窗过程中的任何地方使用它们:

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
    static HBITMAP hbitmap_background = NULL;
    static HBITMAP hbitmap_sprite = NULL;
    switch (msg)
    {
    case WM_CREATE:
    {
        hbitmap_background = (HBITMAP)LoadImage(NULL, 
            L"background.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
        if (!hbitmap_background)
            OutputDebugStringW(L"!hbitmap_backgroundn");
        hbitmap_sprite = (HBITMAP)LoadImage(NULL, 
            L"sprite.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
        if (!hbitmap_sprite)
            OutputDebugStringW(L"!hbitmap_spriten");
    }
    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);
        RECT rc = ps.rcPaint;
        //setup double-buffering:
        HDC memdc = CreateCompatibleDC(hdc);
        HBITMAP membitmap = CreateCompatibleBitmap(hdc, rc.right, rc.bottom);
        HGDIOBJ oldbitmap = SelectObject(memdc, membitmap);
        //double-buffer ready, do custom paintings here:
        FillRect(memdc, &rc, GetSysColorBrush(COLOR_3DFACE));
        DrawBitmap(hbitmap_background, memdc, 0, 0);
        DrawBitmap(hbitmap_sprite, memdc, 0, 0);
        //BitBlt to hdc
        BitBlt(hdc, 0, 0, rc.right, rc.bottom, memdc, 0, 0, SRCCOPY);
        //cleanup:
        SelectObject(hdc, oldbitmap);
        DeleteObject(membitmap);
        DeleteDC(memdc);
        EndPaint(hwnd, &ps);
        return 0;
    }
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    case WM_NCDESTROY:
    {
        //cleapup bitmap handles
        if (hbitmap_background)
            DeleteObject(hbitmap_background);
        if (hbitmap_sprite)
            DeleteObject(hbitmap_sprite);
    }
    }
    return DefWindowProc(hwnd, msg, wp, lp);
} 

我们可以更改DrawBitmap,因此它只需要HBITMAP句柄

void DrawBitmap(HBITMAP hbitmap, HDC hdc, int x, int y)
{
    if (!hbitmap)
    {
        OutputDebugStringW(L"errorn");
        return;
    }
    BITMAP bm;
    GetObject(hbitmap, sizeof(BITMAP), &bm);    
    HDC memdc = CreateCompatibleDC(hdc);
    HGDIOBJ oldbitmap = SelectObject(memdc, hbitmap);
    BitBlt(hdc, x, y, bm.bmWidth, bm.bmHeight, memdc, 0, 0, SRCCOPY);
    SelectObject(memdc, oldbitmap);
    DeleteDC(memdc);
}

请注意,在这个例子中,我假设背景.bmp非常大,而精灵.bmp非常小。如果它以相反的方式绘制,那么背景将隐藏精灵。