Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
888 views
in Technique[技术] by (71.8m points)

winapi - GDI+ double buffering in C++

I haven't written anything with GDI for a while now (and never with GDI+), and I'm just working on a fun project, but for the life of me, I can't figure out how to double buffer GDI+

void DrawStuff(HWND hWnd) {
    HDC          hdc;
    HDC          hdcBuffer;
    PAINTSTRUCT  ps;
    hdc = BeginPaint(hWnd, &ps);
    hdcBuffer = CreateCompatibleDC(hdc);
    Graphics graphics(hdc);
    graphics.Clear(Color::Black);

    // drawing stuff, i.e. bunnies:

    Image bunny(L"bunny.gif");
    graphics.DrawImage(&bunny, 0, 0, bunny.GetWidth(), bunny.GetHeight());  

    BitBlt(hdc, 0,0, WIDTH , HEIGHT, hdcBuffer, 0,0, SRCCOPY);
    EndPaint(hWnd, &ps);
}

The above works (everything renders perfectly), but it flickers. If I change Graphics graphics(hdc); to Graphics graphics(hdcBuffer);, I see nothing (although I should be bitblt'ing the buffer->hWnd hdc at the bottom).

My message pipeline is set up properly (WM_PAINT calls DrawStuff), and I'm forcing a WM_PAINT message every program loop by calling RedrawWindow(window, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW);

I'm probably going about the wrong way to do this, any ideas? The MSDN documentation is cryptic at best.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

CreateCompatibleDC(hdc) creates a DC with a 1x1 pixel monochrome bitmap as its drawing surface. You need to also CreateCompatibleBitmap and select that bitmap into the hdcBuffer if you want a drawing surface larger than that.

Edit:

the flickering is being caused by WM_ERASEBKGND, when you do this

hdc = BeginPaint(hWnd, &ps);

Inside the call to BeginPaint, Windows sends your WndProc a WM_ERASEBKGND message if it thinks the background needs to be redrawn, if you don't handle that message, then DefWindowProc handles it by filling the paint rectangle with your class brush, so to avoid the flickering, you should handle it and return TRUE.

case WM_ERASEBKGND:
   return TRUE; // tell Windows that we handled it. (but don't actually draw anything)

Windows thinks your background should be erased because you tell it that it should, that's what RDW_ERASE means, so you should probably leave that out of your RedrawWindow call


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...