Click to See Complete Forum and Search --> : Best way to call Default Drawing from a WM_PAINT message?


David Giovannini
May 12th, 1999, 03:09 PM
I am writing a basic C++ Win32 app ( no MFC ). I would like to be able to have custom client drawing as well as the default drawing in the same control. I have code that works but is probably not the best or standard way to accomplish this. The following code flickers and causes certain refresh problems.

// this is called from the message dispatcher.
long
CWindow::PaintContent( void )
{
PAINTSTRUCT ps;
HDC hdc = ::BeginPaint( mHandle, &ps );
// this is a virtual method to do custom drawing
this->PaintContentSelf( hdc, ps.rcPaint );
::EndPaint( mHandle, &ps );
return 0;
}

void
CWindow::PaintContentSelf( HDC inHDC, const RECT & inClipRect )
{
// problem with flicker
// first re-invalidate the rect
::InvalidateRect( mHandle, &inClipRect, false );
// send the message back to the parent process
::CallWindowProc( mOldWndProc, mHandle, WM_PAINT, 0, 0);
// for testing draw a red line
HPEN pen = ::CreatePen( PS_DOT, 2, RGB( 255, 0, 0 ) );
::SelectObject( inHDC, pen );
::MoveToEx( inHDC, 0, 0, nil );
::LineTo( inHDC, 20, 20);
::DeleteObject( pen );
}

Any Suggestions would be appreciated.

Thanks
David Giovannini

Paul McKenzie
May 12th, 1999, 04:13 PM
Why do you need to re-Invalidate the window? By doing so, you are posting another WM_PAINT to the message queue.

Another thing is this line in your code:

::CallWindowProc( mOldWndProc, mHandle, WM_PAINT, 0, 0);

If the goal is to call the old window procedure, you should be sending the original wParam and lParam values to the old window procedure, not zeros.

Regards,

Paul McKenzie

David Giovannini
May 12th, 1999, 06:21 PM
You are right, safest thing to do is pass the l and w params. According to docs, the wparam is nothing and the lparam is a possible hdc.

BeginPaint validates the rectangle. Calling the default will do nothing if the rect is not re-invalidated. That is why I called InvalidateRect.

If another WM_PAINT is posted, that will explain the flicker. If I replace the BeginPaint and EndPaint with GetDC and ReleaseDC, I do not need the Invalidate call but I loose any DC processing that BeginPaint does (including giving me the clip rect).

Am I placing too much importance on BeginPaint?

I set my class styles to include CS_(HV)REDRAW. All drawing occured as expected. The code ( excluding wnd register ) looks like

long
CWindow::PaintContent( HDC inHDC )
{
HDC hdc = inHDC;
if ( not inHDC ) hdc = ::GetDC( mHandle );
this->PaintContentSelf( hdc );
if ( not inHDC ) ::ReleaseDC( mHandle, hdc );
return 0;
}

void
CWindow::PaintContentSelf( HDC inHDC )
{
this->DefaultLastMessage(); // preserves params
// more drawing
...
}

Paul McKenzie
May 12th, 1999, 08:45 PM
Try GetUpdateRect(). According to the documentation, this will get you the same clipping region as BeginPaint(). So I would call GetUpdateRect(), the default handler, and then use GetDC / ReleaseDC to do the custom drawing, in that order.

There may not be any need to call BeginPaint(), EndPaint(), or InvalidateRect().

Regards,

Paul McKenzie