scrollpaintwtlbitbltgdi

WTL ScrollWindow efficient painting


With a class derived from CScrollWindowImpl

  void Scroll::DoPaint(CDCHandle hDC)
    {
        if ( _MemDC==NULL)
            return;
        RECT r;

//I'd like to update r with rcPaint from the DC's PAINTSTRUCT here

        hDC.BitBlt(r.left, r.top, r.right-r.left, r.bottom-r.top,
            *_MemDC, r.left, r.top, SRCCOPY);
    }

What is the most efficient way of painting the window contents with a WTL ScrollWindow?

The CScrollImpl WM_PAINT doesn't pass the CPaintDC to the derived class OnPaint, which has the PAINTSTRUCT m_ps member with the update RECT rcPaint member.

LRESULT CScrollImpl::OnPaint(UINT, WPARAM wParam, LPARAM, BOOL&) {
    T* pT = static_cast<T*>(this);
    ATLASSERT(::IsWindow(pT->m_hWnd));
    if(wParam != NULL) { // The HDC is sometimes passed in
        CDCHandle dc = (HDC)wParam;
        dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y);
        pT->DoPaint(dc);
    }
    else {
        CPaintDC dc(pT->m_hWnd);
        dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y);
        pT->DoPaint(CDCHandle(dc));
    }
    return 0;
}

So I've handled the WM_PAINT message and the best I've achieved so far is BitBlt the whole _MemDC when scrolled, but during an unscrolled redraw to only BitBlt the invalidated rectangle.

UPDATE:

Sometimes rcPaint is larger than the rectangle of the MemDc so the increase in efficiency is negligible and buggy.


Solution

  • Is it really the most efficient or not, however note that WTL Samples include Samples\BmpView project which features CScrollWindowImpl use in CBitmapView class, which displays a visible part of a [supposedly large] image. Specifically, it overrides background erase and paint handlers and demostrates how to do BitBlt for the requested for painting part only.