C ++停止显示位图

我怎样才能停止显示我的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_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); } 

我们可以改变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); } 

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