2

我创建了一个效果很好的动画,但它会闪烁。我需要双缓冲方面的帮助,因为我对此一无所知。

这是我的 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);
}
4

1 回答 1

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 函数来获取屏幕位图的尺寸,而不是在那里硬编码 10,或者至少可以#define 宽度和高度值,并在参数中使用这些值。

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

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

于 2010-08-10T22:37:37.387 回答