GDI + C ++中的双缓冲

时间:2010-03-18 22:33:19

标签: c++ winapi gdi+

我暂时没有用GDI写过任何东西(从来没有使用GDI +),我只是在做一个有趣的项目,但对于我的生活,我无法弄清楚如何加倍缓冲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);
}

以上作品(一切都完美呈现),但它闪烁。如果我将Graphics graphics(hdc);更改为Graphics graphics(hdcBuffer);,我什么也看不见(虽然我应该在缓冲区 - > hWnd hdc底部)。

我的消息管道设置正确(WM_PAINT调用DrawStuff),我通过调用RedrawWindow(window, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW);

在每个程序循环强制WM_PAINT消息

我可能会采取错误的方式来做这个,任何想法? MSDN文档充其量是神秘的。

4 个答案:

答案 0 :(得分:7)

CreateCompatibleDC(hdc)创建一个DC,其中1x1像素的单色位图作为绘图表面。如果您希望绘图表面大于该值,您还需要CreateCompatibleBitmap并将该位图选择到hdcBuffer中。

编辑:

当您执行此操作时,WM_ERASEBKGND会导致闪烁

hdc = BeginPaint(hWnd, &ps);

在对BeginPaint的调用中,如果您认为需要重绘背景,Windows会向您的WndProc发送WM_ERASEBKGND消息,如果您不处理该消息,则DefWindowProc会通过填充绘制矩形来处理它。类刷,所以为了避免闪烁,你应该处理它并返回TRUE。

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

Windows认为您的背景应该被删除,因为您告诉它应该删除它,这就是RDW_ERASE的意思,所以您应该将其保留在RedrawWindow电话

之外

答案 1 :(得分:2)

你可以尝试以下方式...

void DrawAll(CDC *pDC)
{
    CRect rect;
    GetClientRect(&rect);

    Bitmap *pMemBitmap = new Bitmap(rect.Width(), rect.Height());

    Graphics* pMemGraphics = Graphics::FromImage(pMemBitmap);

    Graphics graphics(pDC->m_hDC);

    // use pMemGraphics  do something....

    Status status;  
    if ((status = graphics.DrawImage(pMemBitmap, 0, 0)) !=Ok)
    {
        //some error
    }

   delete pMemGraphics;
}

答案 2 :(得分:1)

你在处理WM_ERASEBKGND吗?我相信它会在WM_PAINT之前被调用,并且通常会使窗口的背景颜色变暗,这可能是您不希望发生的。

答案 3 :(得分:0)

鉴于“ Graphics graphics(hdc)”,您似乎正在清除hdc而不是hdcBuffer。果然会导致闪烁。