[英]WM_PAINT handler doesn't perform as it should, flicker-like effect occurs
I have decided to make a test project in MS Visual Studio 2008, in C++ to test a small program in pure WIN32, regarding painting a bitmap as window's background. 我决定在MS Visual Studio 2008中用C ++创建一个测试项目,以在纯WIN32中测试一个小程序,这涉及将位图绘制为窗口的背景。
Window should have gray brush and a bitmap picture stretched over its client area. 窗口应具有灰色画笔,并在其客户区域上展开位图图片。
In my code for WM_PAINT
, if I try to paint gray brush for window, without bitmap, everything seems to work well. 在WM_PAINT
代码中,如果我尝试为没有位图的窗口绘制灰色画笔,那么一切似乎都可以正常工作。
Same goes if I just try to put a bitmap as a background. 如果我只是尝试将位图作为背景,也是如此。
Yet, when I combine these two , so I can get a bitmap picture stretched, and gray background behind bitmap, this is what happens: 但是, 当我将两者结合时 ,可以拉伸位图图片,并在位图后面添加灰色背景,这是发生的情况:
Bitmap picture appears to "stands still", but gray brush appears over entire window for a second, then disappears entirely, so only stretched bitmap is seen, and then appears again, and so on. 位图图片似乎“静止不动”,但是灰色画笔在整个窗口上出现了一秒钟,然后完全消失,因此只能看到拉伸的位图,然后再次出现,依此类推。
It seems as if it is drawn from top going to the bottom, and it seems as if application is doing it all over again. 似乎好像是从上到下绘制的,似乎应用程序又在做一遍。
This is how I see it when I start my program. 这就是我启动程序时看到的样子。
The program was made by choosing option File->New, and then choosing Win32 project from the options. 该程序是通过选择选项文件->新建,然后从选项中选择Win32项目制成的。
Window class was set automatically, and the following members were set like this: 窗口类是自动设置的,以下成员的设置如下:
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
I have added static global variable to store bitmap handle: 我添加了静态全局变量来存储位图句柄:
static HBITMAP bmp;
In the window procedure, made by the wizard, I have initialized it with following code: 在向导创建的窗口过程中,我已使用以下代码对其进行了初始化:
case WM_CREATE:
bmp = LoadBitmap( hInst, MAKEINTRESOURCE(IDB_BITMAP1) );
return 0;
break;
In the window procedure, made by the wizard, I have added WM_PAINT
handler, with following code: 在向导创建的窗口过程中,我添加了WM_PAINT
处理程序,并带有以下代码:
case WM_PAINT:
{
hdc = BeginPaint(hWnd, &ps);
RECT r;
GetClientRect( hWnd, &r );
// TODO: Add any drawing code here...
// fill client area with gray brush, just to test
FillRect( hdc, &r, (HBRUSH)GetStockObject( GRAY_BRUSH ) );
// memory DC for double buffering
HDC MemDC = CreateCompatibleDC( hdc );
// select our bitmap into memory DC
HBITMAP old = (HBITMAP)SelectObject( MemDC, bmp );
// get bitmap's width and height so we can stretch it
BITMAP b;
GetObject( bmp, sizeof(BITMAP), &b );
// stretch our bitmap
StretchBlt( hdc, 0, 0, r.right - r.left, r.bottom - r.top,
MemDC, 0, 0, b.bmWidth, b.bmHeight, SRCCOPY );
// perform proper cleanup
SelectObject( MemDC, old );
DeleteDC(MemDC);
EndPaint(hWnd, &ps);
}
return 0L;
break;
I have also invalidated client area when window is resized, or erasing of background happens, like this: 调整窗口大小或擦除背景时,我也使客户区域无效,如下所示:
case WM_ERASEBKGND:
InvalidateRect( hWnd, NULL, TRUE );
return 1L;
break;
case WM_SIZE:
InvalidateRect( hWnd, NULL, TRUE );
return 0L;
Bitmap is destroyed like this: 位图被破坏是这样的:
case WM_DESTROY:
DeleteObject( bmp );
PostQuitMessage(0);
break;
IMPORTANT NOTE: 重要的提示:
Even if I comment out handlers for WM_SIZE
and WM_ERASEBKGND
, the effect still occurs. 即使我注释掉WM_SIZE
和WM_ERASEBKGND
处理程序,效果仍然会发生。
I do not have much experience with double buffering, but this is simple thing to do. 我对双重缓冲没有太多经验,但这很简单。
I just fail to see the mistake, so I ask more experienced and skillfull colleagues to help. 我只是看不到错误,所以我要求更多有经验和技术娴熟的同事提供帮助。
If additional source code is required, ask for it and I will post it, but until then I will omit it to keep the question brief. 如果需要其他源代码,请提出要求,我将其发布,但在此之前,我将省略它以使问题简短。
You should not call InvalidateRect
in WM_ERASEBKGND
. 您不应在WM_ERASEBKGND
调用InvalidateRect
。 That's just going to force an endless series of paint cycles. 这将迫使无休止的一系列油漆循环。
The job of WM_ERASEBKGND
is to paint the background, and that's all you should ever do. WM_ERASEBKGND
的工作是绘制背景,这是您应该做的所有事情。 If your WM_PAINT
is going to paint the entire window, then there's no need to paint any background. 如果您的WM_PAINT
要绘制整个窗口,则无需绘制任何背景。 In which case, and I think this is your scenario, you should do nothing in WM_ERASEBKGND
. 在这种情况下,我认为这是您的情况,您不应在WM_ERASEBKGND
执行任何操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.