liberte@uiucdcsb.cs.uiuc.edu (12/05/86)
It took several hours for me to figure out how to do the following scrolling trick, so I thought I would maybe save some other people time by posting how I did it, and maybe learn an easier way to do it. What I wanted to do was allow multiple scrolling requests to be accumulated before the window updating actually takes place. This is a desirable behaviour in the case that the update would take along time. The problem is that each scrolling action would normally scroll the whole window some small amount, but this results in the updateRgn returned by scrollRect always overlapping the previous updateRgns, or nearly so. Changing the window origin for each scrolling action does not help matters since the updateRgn is in global coordinates. The solution is to only scroll the good data that remains in the window by subtracting out the previous updateRgn. A further complication is that part of the window may not be on the screen, so one must intersect with the current visible region as well. Another thing I learned along the way was to never switch ports in the middle of an update. It would be handy to be able to write debugging stuff out to Lightspeed Pascals Text window while doing an update, but something isn't properly recovered afterwards. Below is the scrolling code. Dan LaLiberte liberte@b.cs.uiuc.edu liberte@uiuc.csnet ihnp4!uiucdcs!liberte PROCEDURE ContourScroll (dh, dv : integer); { Determine the minimum amount of scrolling required to update the window. } { Only scroll the plotRect, without the previous update region, } { and inside the visible region. ScrollRect then returns the correct update region. } VAR updateRgn : RgnHandle; plotRgn : RgnHandle; copyUpdate : RgnHandle; peek : WindowPeek; ScrollR : Rect; BEGIN SetPort(ContourWindow); peek := WindowPeek(ContourWindow); fixPlotRect; { set up the plotRect once again } { first optain a copy of the current update region } copyUpdate := NewRgn; CopyRgn(peek^.updateRgn, copyUpdate); { give the region local coordinates - note that the updateRgn is in global coordinates } WITH ContourWindow^.portBits.bounds DO OffsetRgn(copyUpdate, left, top); { make a region out of the whole plotting rectangle } plotRgn := NewRgn; RectRgn(plotRgn, plotRect); { remove the current update region } DiffRgn(plotRgn, copyUpdate, plotRgn); { intersect with the current visible region } SectRgn(plotRgn, ContourWindow^.VisRgn, plotRgn); { Get the scrolling rectangle from the resulting region's bounding box } scrollR := plotRgn^^.rgnBBox; DisposeRgn(copyUpdate); DisposeRgn(plotRgn); { Scroll the rectangle and invalidate the returned updateRgn } updateRgn := NewRgn; ScrollRect(scrollR, dh, dv, updateRgn); InvalRgn(updateRgn); DisposeRgn(updateRgn); END;