Author: Tomas Rutkauskas
I need to synchronize three scrollboxes, only one of which will show the
scrollbars. The documentation for TControlScrollBar reads: "If Visible is set to
False, the scroll bar is never visible. This is useful, for example, for
programmatically controlling the scroll position of a form without allowing the
user to control the scroll position." I have been unable to make the scrollbox
scroll when the scrollbar is visible. In fact, the moment you set the scrollbar to
invisible, the position jumps back to 0.
Answer:
I looked at the VCL source for TScrollbox and TControlScrollbar and found the
source of the problem: the TControlscrollbar class has an internal field named
FCalcRange. If you try to set the scrollbar position the passed position is clipped
to the range 0..FCalcRange. The only problem is that FCalcRange is set to 0 when
the scrollbar is set to invisible, so Position will always be set to 0, regardless
of what you try to set it to. I see no way around that, so you need to use a
different strategy: instead of using the invisible scrollbars for the two slave
scrollboxes scroll them directly, using ScrollBy.
The following example uses three scrollboxes of same size and scroll ranges.
AutoScroll and Autosize are false for all, the first two have invisible scrollbars,
the last has visible scrollbars and controls the other two. Each scrollbox has an
edit in it so there is something visible to scroll around.
1 unit Unit1;
2
3 interface
4
5 uses
6 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
7 StdCtrls;
8
9 type
10 TForm1 = class(TForm)
11 ScrollBox1: TScrollBox;
12 Edit1: TEdit;
13 ScrollBox2: TScrollBox;
14 Edit2: TEdit;
15 ScrollBox3: TScrollBox;
16 Edit3: TEdit;
17 procedure FormCreate(Sender: TObject);
18 private
19 { Private declarations }
20 FOldProc: TWndMethod;
21 procedure NewProc(var msg: TMessage);
22
23 public
24 { Public declarations }
25 end;
26
27 var
28 Form1: TForm1;
29
30 implementation
31
32 {$R *.DFM}
33
34 procedure TForm1.FormCreate(Sender: TObject);
35 begin
36 FoldProc := Scrollbox3.WindowProc;
37 Scrollbox3.WindowProc := NewProc;
38 end;
39
40 procedure TForm1.NewProc(var msg: TMessage);
41 var
42 oldpos, newpos: Integer;
43 begin
44 case msg.Msg of
45 WM_VSCROLL:
46 begin
47 oldpos := scrollbox3.VertScrollBar.Position;
48 FoldProc(msg);
49 newpos := scrollbox3.VertScrollBar.Position;
50 if oldpos <> newpos then
51 begin
52 scrollbox1.ScrollBy(0, oldpos - newpos);
53 scrollbox2.ScrollBy(0, oldpos - newpos);
54 end;
55 end;
56 WM_HSCROLL:
57 begin
58 oldpos := scrollbox3.HorzScrollBar.Position;
59 FoldProc(msg);
60 newpos := scrollbox3.HorzScrollBar.Position;
61 if oldpos <> newpos then
62 begin
63 scrollbox1.ScrollBy(oldpos - newpos, 0);
64 scrollbox2.ScrollBy(oldpos - newpos, 0);
65 end;
66 end
67 else
68 FoldProc(msg);
69 end;
70 end;
71
72 end.
|