帮助双缓冲

发布于 2024-09-13 23:05:36 字数 858 浏览 4 评论 0原文

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

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

I have created an animation which works fine, but it flicks. I need help with double-buffering since I don't know anything about it.

This is the code in my onPaint():

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

It works fine but with flicker. I tried this code but it didn't work:

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);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

鱼窥荷 2024-09-20 23:05:36

看来您只是过早地将屏外 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() 调用,以便它在离屏地图上的所有绘图操作之后发生。

It looks like you're just prematurely copying the offscreen DC to the display. Try moving the call to BitBlt down four lines, to make it the last line before you start the clean-up, like so:

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);
}

Another thing about this code, you've passed the constant '10' as the width and height of your off-screen bitmap, as well as using it for the width and height params to the BitBlt() that does the copy. Chances are the window client area being updated is very much larger than that. The 'black square' is a consequence of blitting the 10x10 off-screen map onto the window client area. Instead of hard-coding 10 there, you might try using another GDI function to obtain the dimensions of the on-screen bitmap, or at the very least you could #define width and height values, and use these in the params.

The other thing killing you is probably the 'sf' in the line "graphics.DrawEllipse(&pen, sf , 0, 10, 10)" -- since you've created an incredibly tiny 10x10 map, if the value of 'sf' is anything outside of 0..10, the DrawEllipse() call will place the ellipse entirely outside of the available pixels in your offscreen map.

So, bottom line, you probably want to make the offscreen map the same size as the window client area, and be sure to move the BitBlt() call down so that it happens after all the drawing ops on the off-screen map.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文