Author: Jonas Bilinkevicius
Is there a way of finding out - during or immediately after the fact - that a
control has been scrolled? For instance, say someone moves the scroll thumb in a
TMemo. Is there a message I can intercept that says this occurred? I don't really
need to know which direction or by how much, just that it happened.
Answer:
Here's unit that shows one way to do this without having to create a descendent. It
will let you know about "direct" scrolls, but not about scrolls that happen because
of cursor movement through the memo's text, etc. It will also report a scroll if
the user merely clicked on the thumb track without moving it (without actually
scrolling).
To see the code in action, you will need to fill a TMemo with enough text so that
it is necessary to scroll.
1 unit ScrollCatchU;
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 Memo1: TMemo;
12 ClearButton: TButton;
13 ScrolledLabel: TLabel;
14 procedure FormCreate(Sender: TObject);
15 procedure ClearButtonClick(Sender: TObject);
16 private
17 Counter: cardinal;
18 procedure Memo1ScrollCatcher(var message: TMessage);
19 public
20 end;
21
22 var
23 Form1: TForm1;
24
25 implementation
26
27 {$R *.DFM}
28
29 type
30 TMyControl = class(TControl);
31
32 procedure TForm1.Memo1ScrollCatcher(var message: TMessage);
33 begin
34 Inc(Counter); {for testing/ diagnostics only ...}
35 {Add commented out section below, if you only want the "last" scroll
36 message in a sequence}
37 if ((message.Msg = WM_VSCROLL) or (message.Msg = WM_HSCROLL))
38 { and (TWMVScroll(Message).ScrollCode = SB_ENDSCROLL) }then
39 ScrolledLabel.caption := 'Scrolled';
40 { caption := format('Message: %d ScrollCode: %d Counter: %d', [Message.Msg,
41 TWMVScroll(Message).ScrollCode, Counter]); }
42 TMyControl(Memo1).WndProc(message);
43 end;
44
45 procedure TForm1.FormCreate(Sender: TObject);
46 begin
47 Memo1.WindowProc := Memo1ScrollCatcher;
48 Counter := 0;
49 ClearButtonClick(nil);
50 end;
51
52 procedure TForm1.ClearButtonClick(Sender: TObject);
53 begin
54 ScrolledLabel.Caption := '';
55 {Using a manual "reset" for the "Scrolled" display}
56 end;
57
58 end.
This technique can be used with any TControl descendent.
You might want to add the Windows Mouse Wheel message to the ones that routine is
looking for. Something like:
59 { ... }
60 if ((message.Msg = WM_VSCROLL) or (message.Msg = WM_HSCROLL)
61 or (message.Msg = WM_MOUSEWHEEL))
62 {and (TWMVScroll(Message).ScrollCode = SB_ENDSCROLL)}then
63 ScrolledLabel.caption := 'Scrolled';
64 { ... }
Of course, if you are just fishing for the SB_ENDSCROLL ScrollCode with the other messages, you'll have to separate the test for this message out a little further.
|