How to get Scrollbar notifications from a TMemo control?

1.9k views Asked by At

I have a VCL TMemo control and need to be notified every time the text is scrolled. There is no OnScroll event and the scroll messages doesn't seem to propagate up to the parent form.

Any idea of how to get the notification? As a last resort I can place an external TScrollBar and update the TMemo in the OnScroll event, but then I have to keep them in sync when I move the cursor or scroll the mouse wheel in TMemo...

2

There are 2 answers

4
Remy Lebeau On BEST ANSWER

You can subclass the Memo's WindowProc property at runtime to catch all of messages sent to the Memo, eg:

private:
    TWndMethod PrevMemoWndProc;
    void __fastcall MemoWndProc(TMessage &Message);

__fastcall TMyForm::TMyForm(TComponent *Owner)
    : TForm(Owner)
{
    PrevMemoWndProc = Memo1->WindowProc;
    Memo1->WindowProc = MemoWndProc;
}

void __fastcall TMyForm::MemoWndProc(TMessage &Message)
{
    switch (Message.Msg)
    {
        case CN_COMMAND:
        {
            switch (reinterpret_cast<TWMCommand&>(Message).NotifyCode)
            {
                case EN_VSCROLL:
                {
                    //...
                    break;
                }

                case EN_HSCROLL:
                {
                    //...
                    break;
                }
            }

            break;
        }

        case WM_HSCROLL:
        {
            //...
            break;
        }

        case WM_VSCROLL:
        {
            //...
            break;
        }
    }

    PrevMemoWndProc(Message);
}
3
RRUZ On

You can use a interposer class to handle the WM_VSCROLL and WM_HSCROLL messages and the EN_VSCROLL and EN_HSCROLL notification codes (exposed through the WM_COMMAND message).

Try this sample

type
  TMemo  = class(Vcl.StdCtrls.TMemo)
  private
   procedure CNCommand(var Message: TWMCommand); message CN_COMMAND;
   procedure WMVScroll(var Msg: TWMHScroll); message WM_VSCROLL;
   procedure WMHScroll(var Msg: TWMHScroll); message WM_HSCROLL;
  end;

  TForm16 = class(TForm)
    Memo1: TMemo;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form16: TForm16;

implementation

{$R *.dfm}


{ TMemo }

procedure TMemo.CNCommand(var Message: TWMCommand);
begin
   case Message.NotifyCode of
    EN_VSCROLL : OutputDebugString('EN_VSCROLL');
    EN_HSCROLL : OutputDebugString('EN_HSCROLL');
   end;

   inherited ;
end;

procedure TMemo.WMHScroll(var Msg: TWMHScroll);
begin
   OutputDebugString('WM_HSCROLL') ;
   inherited;
end;

procedure TMemo.WMVScroll(var Msg: TWMHScroll);
begin
   OutputDebugString('WM_HSCROLL') ;
   inherited;
end;