[15] | 1 | Unit ControlScrolling;
|
---|
| 2 |
|
---|
| 3 | Interface
|
---|
| 4 |
|
---|
| 5 | uses
|
---|
| 6 | Forms, Classes;
|
---|
| 7 |
|
---|
| 8 | Procedure ScrollControlRect( Control: TControl;
|
---|
| 9 | Rect: TRect;
|
---|
| 10 | XScrollDistance, YScrollDistance: longint;
|
---|
| 11 | BackGroundColor: TColor;
|
---|
| 12 | Smooth: boolean );
|
---|
| 13 |
|
---|
| 14 | Implementation
|
---|
| 15 |
|
---|
| 16 | uses
|
---|
| 17 | Os2Def, PmWin, PmGpi, Graphics;
|
---|
| 18 |
|
---|
| 19 | Procedure ScrollRect( Control: TControl;
|
---|
| 20 | Rect: TRect;
|
---|
| 21 | XScrollDistance, YScrollDistance: longint;
|
---|
| 22 | BackGroundColor: TColor );
|
---|
| 23 | var
|
---|
| 24 | SourceRect: RECTL;
|
---|
| 25 | InvalidRegion: HRGN;
|
---|
| 26 | rc: APIRET;
|
---|
| 27 | begin
|
---|
| 28 | SourceRect:= RECTL( Rect );
|
---|
| 29 | inc( SourceRect.yTop, 1 ); // WinScrollWindow expects top/right + 1
|
---|
| 30 | inc( SourceRect.xRight, 1 );
|
---|
| 31 |
|
---|
| 32 | InvalidRegion:= GpiCreateRegion( Control.Canvas.Handle, 0, nil );
|
---|
| 33 | WinScrollWindow( Control.Handle,
|
---|
| 34 | XScrollDistance,
|
---|
| 35 | YScrollDistance,
|
---|
| 36 | SourceRect,
|
---|
| 37 | SourceRect, // destination clip
|
---|
| 38 | InvalidRegion,
|
---|
| 39 | nil,
|
---|
| 40 | SW_INVALIDATERGN );
|
---|
| 41 |
|
---|
| 42 | // Clear the invalidated area.
|
---|
| 43 | Control.Canvas.Pen.Color := BackgroundColor;
|
---|
| 44 | Control.Canvas.Brush.Style:= bsSolid;
|
---|
| 45 | rc:= GpiPaintRegion( Control.Canvas.Handle, InvalidRegion );
|
---|
| 46 |
|
---|
| 47 | GpiDestroyRegion( Control.Canvas.Handle, InvalidRegion );
|
---|
| 48 | end;
|
---|
| 49 |
|
---|
| 50 | Function FSign( arg: double ): double;
|
---|
| 51 | begin
|
---|
| 52 | if arg>0 then
|
---|
| 53 | Result:= 1
|
---|
| 54 | else if arg<0 then
|
---|
| 55 | Result:= -1
|
---|
| 56 | else
|
---|
| 57 | Result:= 0;
|
---|
| 58 | end;
|
---|
| 59 |
|
---|
| 60 | Function Sign( arg: longint ): longint;
|
---|
| 61 | begin
|
---|
| 62 | if arg>0 then
|
---|
| 63 | Result:= 1
|
---|
| 64 | else if arg<0 then
|
---|
| 65 | Result:= -1
|
---|
| 66 | else
|
---|
| 67 | Result:= 0;
|
---|
| 68 | end;
|
---|
| 69 |
|
---|
| 70 | Procedure ScrollControlRect( Control: TControl;
|
---|
| 71 | Rect: TRect;
|
---|
| 72 | XScrollDistance, YScrollDistance: longint;
|
---|
| 73 | BackGroundColor: TColor;
|
---|
| 74 | Smooth: boolean );
|
---|
| 75 | var
|
---|
| 76 | LastTime: ULONG;
|
---|
| 77 | X, Y: double;
|
---|
| 78 | XScrolled, YScrolled: longint;
|
---|
| 79 | NextX, NextY: double;
|
---|
| 80 | Width: longint;
|
---|
| 81 | Height: longint;
|
---|
| 82 | XScrollStep: double;
|
---|
| 83 | YScrollStep: double;
|
---|
| 84 | XScrollAmount: longint;
|
---|
| 85 | YScrollAmount: longint;
|
---|
| 86 | begin
|
---|
| 87 | Height:= Rect.Top - Rect.Bottom + 1;
|
---|
| 88 | Width:= Rect.Right - Rect.Left + 1;
|
---|
| 89 |
|
---|
| 90 | if ( XScrollDistance = 0 )
|
---|
| 91 | and ( YScrollDistance = 0 ) then
|
---|
| 92 | exit;
|
---|
| 93 |
|
---|
| 94 | if ( Abs( XScrollDistance ) >= Width )
|
---|
| 95 | or ( Abs( YScrollDistance ) >= Height ) then
|
---|
| 96 | begin
|
---|
| 97 | // scrolling more than a screen in height
|
---|
| 98 | Control.InvalidateRect( Rect );
|
---|
| 99 | exit;
|
---|
| 100 | end;
|
---|
| 101 |
|
---|
| 102 | if not Smooth then
|
---|
| 103 | begin
|
---|
| 104 | ScrollRect( Control,
|
---|
| 105 | Rect,
|
---|
| 106 | XScrollDistance,
|
---|
| 107 | YScrollDistance,
|
---|
| 108 | BackGroundColor );
|
---|
| 109 |
|
---|
| 110 | exit;
|
---|
| 111 | end;
|
---|
| 112 | Y:= 0;
|
---|
| 113 | X:= 0;
|
---|
| 114 | XScrolled:= 0;
|
---|
| 115 | YScrolled:= 0;
|
---|
| 116 |
|
---|
| 117 | if XScrollDistance <> 0 then
|
---|
| 118 | begin
|
---|
| 119 | XScrollStep:= Abs( XScrollDistance ) / 10.0
|
---|
| 120 | + 0.0001; // add a small amount so we always add up to at least scrolldistance
|
---|
| 121 | // no less than 1 pixel
|
---|
| 122 | if XScrollStep < 1 then
|
---|
| 123 | XScrollStep:= 1;
|
---|
| 124 | end
|
---|
| 125 | else
|
---|
| 126 | XScrollStep:= 0;
|
---|
| 127 |
|
---|
| 128 | if YScrollDistance <> 0 then
|
---|
| 129 | begin
|
---|
| 130 | YScrollStep:= Abs( YScrollDistance ) / 10.0
|
---|
| 131 | + 0.0001; // add a small amount so we always add up to at least scrolldistance
|
---|
| 132 |
|
---|
| 133 | if YScrollStep < 1 then
|
---|
| 134 | YScrollStep:= 1;
|
---|
| 135 | end
|
---|
| 136 | else
|
---|
| 137 | YScrollStep:= 0;
|
---|
| 138 |
|
---|
| 139 | while ( XScrolled < Abs( XScrollDistance ) )
|
---|
| 140 | or ( YScrolled < Abs( YScrollDistance ) ) do
|
---|
| 141 | begin
|
---|
| 142 | LastTime:= WinGetCurrentTime( AppHandle );
|
---|
| 143 |
|
---|
| 144 | NextX:= X + XScrollStep;
|
---|
| 145 | NextY:= Y + YScrollStep;
|
---|
| 146 |
|
---|
| 147 | XScrollAmount:= trunc( NextX ) - trunc( X );
|
---|
| 148 | YScrollAmount:= trunc( NextY ) - trunc( Y );
|
---|
| 149 |
|
---|
| 150 | ScrollRect( Control,
|
---|
| 151 | Rect,
|
---|
| 152 | XScrollAmount * sign( XScrollDistance ),
|
---|
| 153 | YScrollAmount * sign( YScrollDistance ),
|
---|
| 154 | BackGroundColor );
|
---|
| 155 |
|
---|
| 156 | X:= X + XScrollStep;
|
---|
| 157 | Y:= Y + YScrollStep;
|
---|
| 158 |
|
---|
| 159 | inc( XScrolled, XScrollAmount );
|
---|
| 160 | inc( YScrolled, YScrollAmount );
|
---|
| 161 |
|
---|
| 162 | // wait at least 5 ms
|
---|
| 163 | while WinGetCurrentTime( AppHandle ) - LastTime < 5 do
|
---|
| 164 | ;
|
---|
| 165 | end;
|
---|
| 166 | end;
|
---|
| 167 |
|
---|
| 168 | Initialization
|
---|
| 169 | End.
|
---|