How to detect if a TMemo has been scrolled (Views: 2141)
Problem/Question/Abstract: 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. unit ScrollCatchU; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Memo1: TMemo; ClearButton: TButton; ScrolledLabel: TLabel; procedure FormCreate(Sender: TObject); procedure ClearButtonClick(Sender: TObject); private Counter: cardinal; procedure Memo1ScrollCatcher(var Message: TMessage); public end; var Form1: TForm1; implementation {$R *.DFM} type TMyControl = class(TControl); procedure TForm1.Memo1ScrollCatcher(var Message: TMessage); begin Inc(Counter); {for testing/ diagnostics only ...} {Add commented out section below, if you only want the "last" scroll message in a sequence} if ((Message.Msg = WM_VSCROLL) or (Message.Msg = WM_HSCROLL)) { and (TWMVScroll(Message).ScrollCode = SB_ENDSCROLL) }then ScrolledLabel.caption := 'Scrolled'; { caption := format('Message: %d ScrollCode: %d Counter: %d', [Message.Msg, TWMVScroll(Message).ScrollCode, Counter]); } TMyControl(Memo1).WndProc(Message); end; procedure TForm1.FormCreate(Sender: TObject); begin Memo1.WindowProc := Memo1ScrollCatcher; Counter := 0; ClearButtonClick(nil); end; procedure TForm1.ClearButtonClick(Sender: TObject); begin ScrolledLabel.Caption := ''; {Using a manual "reset" for the "Scrolled" display} end; 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: { ... } if ((Message.Msg = WM_VSCROLL) or (Message.Msg = WM_HSCROLL) or (Message.Msg = WM_MOUSEWHEEL)) {and (TWMVScroll(Message).ScrollCode = SB_ENDSCROLL)}then ScrolledLabel.caption := 'Scrolled'; { ... } 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. |