CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4
  1. #1
    Join Date
    Mar 1999
    Location
    St. Louis
    Posts
    45

    Best way to call Default Drawing from a WM_PAINT message?

    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);
    :eleteObject( pen );
    }

    Any Suggestions would be appreciated.

    Thanks
    David Giovannini



  2. #2
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Best way to call Default Drawing from a WM_PAINT message?

    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


  3. #3
    Join Date
    Mar 1999
    Location
    St. Louis
    Posts
    45

    Re: Best way to call Default Drawing from a WM_PAINT message?

    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
    ...
    }


  4. #4
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Best way to call Default Drawing from a WM_PAINT message?

    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


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured