0
votes

INTRODUCTION:

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.

PROBLEM:

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.

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.

RELEVANT INFORMATION:

The program was made by choosing option File->New, and then choosing Win32 project from the options.

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:

    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.

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.

1
Don't call InvalidateRect in WM_ERASEBKGND. Your job there is to erase the background. - David Heffernan
It seems that it works, if you are sure that was the problem, post an answer, I will accept and upvote it. Thank you. Regards. - AlwaysLearningNewStuff

1 Answers

3
votes

You should not call InvalidateRect in WM_ERASEBKGND. 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. If your WM_PAINT is going to paint the entire window, then there's no need to paint any background. In which case, and I think this is your scenario, you should do nothing in WM_ERASEBKGND.