GDI+ C++ 中的双缓冲
一段时间没有用 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);
}
我已经有 有效(一切都渲染得很完美),但它会闪烁。如果我将 Graphicsgraphics(hdc);
更改为 Graphicsgraphics(hdcBuffer);
,我什么也看不到(尽管我应该对 buffer->hWnd hdc 进行 bitblt'ing)底部)。
我的消息管道已正确设置(WM_PAINT 调用 DrawStuff),并且我通过调用 RedrawWindow(window, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW); 来强制每个程序循环发送 WM_PAINT 消息;
I'我可能采用了错误的方法来做到这一点,有什么想法吗? MSDN 文档充其量是晦涩难懂的。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
CreateCompatibleDC(hdc)
创建一个以 1x1 像素单色位图作为其绘图表面的 DC。如果您想要大于该值的绘图表面,您还需要CreateCompatibleBitmap
并将该位图选择到 hdcBuffer 中。编辑:
闪烁是由 WM_ERASEBKGND 引起的,当您
在对 BeginPaint 的调用中执行此操作时,Windows 会向您的 WndProc 发送 WM_ERASEBKGND 消息,如果它认为背景需要重绘,如果您不处理该消息,则 DefWindowProc 通过使用您的类画笔填充绘画矩形来处理它,所以为了避免闪烁,你应该处理它并返回 TRUE。
Windows 认为您的背景应该被删除,因为您告诉它应该删除,这就是 RDW_ERASE 的含义,因此您应该将其排除在您的 RedrawWindow 调用之外
CreateCompatibleDC(hdc)
creates a DC with a 1x1 pixel monochrome bitmap as its drawing surface. You need to alsoCreateCompatibleBitmap
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
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.
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 yourRedrawWindow
call您可以尝试以下方法:
You can try the following way:
您正在处理 WM_ERASEBKGND 吗?我相信它会在 WM_PAINT 之前被调用,并且通常会位图窗口的背景颜色,而您可能不希望发生这种情况。
Are you handling WM_ERASEBKGND? I believe it gets called right before WM_PAINT and usually blits the window's background color which you probably don't want to happen.
鉴于“Graphics Graphics(hdc)”,您似乎正在清除 hdc 而不是 hdcBuffer。果然,这会引起闪烁。
Given "Graphics graphics(hdc)", you seem to be clearing hdc instead of hdcBuffer. Sure enough, that will cause flicker.