简体   繁体   English

C++ 停止显示位图

[英]C++ Stop displaying bitmap

How can I stop displaying the bitmap in my Win32 Project.如何停止在我的 Win32 项目中显示位图。 I have a method that I'm calling in WM_PAINT called LoadBitmap.我有一个在 WM_PAINT 中调用的方法,称为 LoadBitmap。 It's code looks like this:它的代码如下所示:

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;

}

NOTE x and y change continuously.注意x 和 y 不断变化。 When x and y change however, the previous instance of them stays behind.然而,当 x 和 y 发生变化时,它们的前一个实例会留在后面。

How can I stop displaying a bitmap once it has been painted in a new position?位图在新位置绘制后如何停止显示?

If there is background brush then the old bitmap is erased with each paint call.如果有背景画笔,则每次绘制调用都会擦除旧位图。 If there is no background then erase it manually for example with FillRect Here is example with double buffering, assumes there is no background brush.如果没有背景,则手动擦除它,例如使用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;
}

Edit *************编辑************

It will be faster to load the bitmap file only once.只加载一次位图文件会更快。 For each paint request, we need only to draw the bitmap, instead of LoadImage every time + draw.对于每个绘制请求,我们只需要绘制位图,而不是每次+绘制时加载图像。

You can declare HBITMAP handles as static values in window's procedure.您可以在窗口过程中将HBITMAP句柄声明为静态值。 Set it up once in WM_CREATE , and clean it up in WM_NCDESTROY .WM_CREATE设置一次,并在WM_NCDESTROY清理它。 Now we can use them anywhere in side window procedure:现在我们可以在侧窗程序的任何地方使用它们:

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_background\n");

        hbitmap_sprite = (HBITMAP)LoadImage(NULL, 
            L"sprite.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
        if (!hbitmap_sprite)
            OutputDebugStringW(L"!hbitmap_sprite\n");
    }

    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);
} 

We can change DrawBitmap so it only needs HBITMAP handle我们可以改变DrawBitmap所以它只需要HBITMAP句柄

void DrawBitmap(HBITMAP hbitmap, HDC hdc, int x, int y)
{
    if (!hbitmap)
    {
        OutputDebugStringW(L"error\n");
        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);
}

Note, in this example I assume background.bmp is very large, and sprite.bmp is very small.注意,在这个例子中,我假设 background.bmp 非常大,而 sprite.bmp 非常小。 If it is painted the other way around then background will hide the sprite.如果它以相反的方式绘制,则背景将隐藏精灵。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM