WM_PAINT处理程序没有按预期执行,发生类似闪烁的效果

时间:2013-09-22 13:17:02

标签: c++ winapi

引言:

我决定在MS Visual Studio 2008中用C ++编写一个测试项目来测试纯WIN32中的一个小程序,关于将位图绘制为窗口的背景。

问题:

窗口应该有灰色画笔,并且位图图片在其客户区域上延伸。

在我的WM_PAINT代码中,如果我尝试为窗口绘制灰色画笔,没有位图,一切似乎都运行良好。

如果我只是尝试将位图作为背景,也一样。

然而,当我将这两个组合在一起时,我可以得到拉伸的位图图片,以及位图背后的灰色背景,这就是:

位图图片显示为“静止不动”,但灰色画笔在整个窗口上显示一秒钟,然后完全消失,因此只能看到拉伸的位图,然后再次出现,依此类推。

好像它是从顶部绘制到底部,似乎应用程序正在重新进行。

这是我开始学习课程时的看法。

相关信息:

该程序是通过选择File-> New选项,然后从选项中选择Win32项目。

自动设置了窗口类,并且以下成员设置如下:

   wcex.style = CS_HREDRAW | CS_VREDRAW;

   wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);

我添加了静态全局变量来存储位图句柄:

   static HBITMAP bmp;

在向导的窗口过程中,我使用以下代码初始化它:

   case WM_CREATE:

        bmp = LoadBitmap( hInst, MAKEINTRESOURCE(IDB_BITMAP1) );

        return 0;

        break;

在向导的窗口过程中,我添加了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;

当调整窗口大小或删除背景时,我也使客户区无效,如下所示:

   case WM_ERASEBKGND:

        InvalidateRect( hWnd, NULL, TRUE );

        return 1L;
        break;

   case WM_SIZE:

        InvalidateRect( hWnd, NULL, TRUE );

        return 0L;

Bitmap像这样被破坏:

   case WM_DESTROY:

        DeleteObject( bmp );

        PostQuitMessage(0);
        break;

重要提示:

即使我评论WM_SIZEWM_ERASEBKGND的处理程序,效果仍然会发生。

我对双缓冲没有多少经验,但这很简单。

我只是没有看到错误,所以我请更多有经验和技巧娴熟的同事帮忙。

如果需要其他源代码,请求它,我会发布,但在此之前我会省略它以保持问题简短。

1 个答案:

答案 0 :(得分:3)

您不应在InvalidateRect中致电WM_ERASEBKGND。这只是迫使一系列无休止的油漆循环。

WM_ERASEBKGND的工作是绘制背景,这就是你应该做的一切。如果你的WM_PAINT要绘制整个窗口,那么就不需要绘制任何背景。在这种情况下,我认为这是您的方案,您应该在WM_ERASEBKGND中无所作为。