Overlay Drawing in CScrollView – Part 1

The problem

If we want to make a simple image viewer with scroll capability, CScrollView MFC class is great. Let’s say, we have a CBitmap object in the document class, that keeps the image to be displayed. All we have to do in the view’s class (derived from CScrollView) is something like this:

  1. Override CScrollView::OnUpdate virtual function and set the scroll sizes according to the image sizes.
  2. Override CScrollView::OnDraw virtual function and draw the image.

No sweat, like a walking in the park! Of course, we can further improve it by adding more features, like image zoom and so on.
Now, let’s say, we have to draw a text over the image in a fixed position. One first attempt would be to simply draw the text in view’s client area, after the bitmap has been bit-blitted, like in the next example:

It is not working OK: when scrolling the view, some weird “effects” occur. Let’s see a little “movie” that shows what happens when the user scrolls the view.

  1. Let’s say we have loaded and displayed a bitmap. Additionally, using the code from above examples, we wrote a little text in the top-left corner of the view.

    Before ScrollWindow

    Before ScrollWindow

  2. When the user clicks in the vertical scrollbar, the view window receives WM_VSCROLL message with SB_PAGEDOWN scroll-bar code. If put a breakpoint in the beginning of OnDraw, the image looks like this:
    After ScrollWindow  and before OnDraw

    After ScrollWindow and before OnDraw

    Somewhere in CScrollView implementation, the ScrollWindow function has been called. That simply shifted up the contents of the view. The remained area from the bottom side is invalidated in order to be further drawn in WM_PAINT message handler (in case of views, OnDraw virtual function).

  3. Finally, when OnDraw function is done, we get this:

    After OnDraw

    After OnDraw

Hmmn…the text has been moved up, even in OnDraw we’ve tried to put it back at the same coordinates. That’s because ScrollWindow moved up the area which contains the text. Besides, the area containing the text was not invalidated, so TextOut did nothing. Of course anyone can say: “it’s easy from now, just invalidate the whole view’s client area, somewhere at the end of scroll message handler”. Yes, may be a little bit better but still not OK. When scrolling, the text will “jump” and flicker.

In CODEPERT forum, we discussed different ideas for overcoming this problem, including the using of layered windows (that works quite fain but still rises some issues). Next time, I’ll show the best solution we found. Just keep in touch!


See also


Leave a Reply