帮助双缓冲

时间:2010-08-10 22:27:20

标签: c++ gdi doublebuffered

我已经创建了一个可以正常工作的动画,但是它很轻松。我需要双缓冲的帮助,因为我对它一无所知。

这是我的onPaint()中的代码:

VOID onPaint(HDC hdc)
{
    Graphics graphics(hdc);
    Pen      pen(Color(255, 0, 0, 255));
    graphics.DrawEllipse(&pen, sf , 0, 10, 10);
}

它工作正常,但闪烁。我尝试了这段代码,但它不起作用:

VOID onPaint(HDC hdc,HWND hWnd)
{
    HDC hDC=GetDC(hWnd);;
    HDC memDC = CreateCompatibleDC(hDC);
    HBITMAP hMemBmp = CreateCompatibleBitmap(hDC,10,10);
    HBITMAP hOldBmp =  (HBITMAP)SelectObject(memDC,hMemBmp);
    BitBlt(hDC, 0, 0, 10, 10, memDC, 0, 0, SRCCOPY);
    Graphics graphics(memDC);
    Pen      pen(Color(255, 0, 0, 255));
    graphics.DrawEllipse(&pen, sf , 0, 10, 10);

    // Always select the old bitmap back into the device context
    SelectObject(memDC, hOldBmp);
    DeleteObject(hMemBmp);
    DeleteDC(memDC);
}

1 个答案:

答案 0 :(得分:9)

看起来你只是过早地将屏幕外DC复制到显示器上。尝试将调用移动到BitBlt四行,使其成为开始清理之前的最后一行,如下所示:

VOID onPaint(HDC hdc,HWND hWnd)
{
    // this line looks a little odd :
    HDC hDC = GetDC(hWnd);
    // .. usually the hdc parameter passed to onPaint would already refer to
    // the on-screen DC that windows wants updated. Also worth noting is that
    // when you use GetDC(), you should have a matching ReleaseDC()
    // As a quick test, you might just replace the above line with
    //     HDC hDC = hdc;

    HDC memDC = CreateCompatibleDC(hDC);
    HBITMAP hMemBmp = CreateCompatibleBitmap(hDC,10,10);
    HBITMAP hOldBmp =  (HBITMAP)SelectObject(memDC,hMemBmp);

    // draw to the off-screen map ..
    Graphics graphics(memDC);
    Pen      pen(Color(255, 0, 0, 255));
    graphics.DrawEllipse(&pen, sf , 0, 10, 10);

    // now that you've drawn on the offscreen map, go ahead
    // and put it on screen.
    BitBlt(hDC, 0, 0, 10, 10, memDC, 0, 0, SRCCOPY);

    // Always select the old bitmap back into the device context
    SelectObject(memDC, hOldBmp);
    DeleteObject(hMemBmp);
    DeleteDC(memDC);
}

关于这段代码的另一件事,你已经将常量'10'作为离屏位图的宽度和高度传递,并将其用作宽度和高度参数,用于执行复制的BitBlt() 。机会是正在更新的窗口客户端区域比这大得多。 “黑色方块”是将10x10离屏地图映射到窗口客户区域的结果。您可以尝试使用另一个GDI函数来获取屏幕上位图的尺寸,或者至少可以#define宽度和高度值,并在参数中使用这些,而不是在那里进行硬编码10。

杀死你的另一件事可能就是“graphics.DrawEllipse(& pen,sf,0,10,10)”中的“sf” - 因为你创造了一个非常小的10x10地图,如果'sf'的值是0..10之外的任何值,DrawEllipse()调用将把椭圆完全置于屏幕外地图中可用像素之外。

所以,最重要的是,您可能希望使屏幕外地图的大小与窗口客户端区域相同,并确保将BitBlt()调用向下移动,以便在屏幕外的所有绘图操作之后发生地图。