Link to home
Start Free TrialLog in
Avatar of davegreen
davegreen

asked on

Scrolling 2 Richedit controls in sync

I have 2 richedit controls. I want to scroll one of them in sync with the other... so that if I cursor up/down or scroll using the scroll bar, the other richedit scrolls with it. Anyone have any ideas for the best way to do this?
Avatar of rwilson032697
rwilson032697

Create a component derived from TRichEdit and override the WM_HSCROLL and WM_VSCROLL messages. In the handlers for these messages send a copy of them to the second memo which will then scroll in step with the first memo.

Cheers,

Raymond.
Avatar of davegreen

ASKER

Thanks for a quick response!

I am actually using two WPTools Richedits... have you got any example code to give me more of an idea what to do?
You are too quick Dave!

After dashing off that quick answer I decided to give it a go. I am very embarassed to say the initial approach I outlined does not appear to work. I also tried overriding the WM_NCHITTEST message and passing that along but again this didn't work.

You should reject my answer and allow other experts to answer it. My apologies.

Cheers,

Raymond.

Thanks Raymond,
Well in theory it seems easy to do..but I have yet to come p with a solution. Still its not a thing you need to do everyday.

Dave
Have you tried sending an EM_SCROLL message?
Dave, I wrote this (code below), which DOES work in terms of keeping them in sync when the user click on a scroll bar (I actually messed up the first attempt which is why it didn't work :-( )

Unfortunately this doesn't deal with the user arrowing down. Though I think this could be done with using EM_GETFIRSTVISIBLELINE and EM_SETFIRSTVISIBLELINE in the OnChange event (I havn't tried it out yet - I'll let you know how I go...)

I also tried EM_SCROLL (as Philipleighs suggested), but for some reason the control does not appear to be sent that message.

Cheers,

Raymond.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls;

type
  TMyRichEdit = class(TRichEdit)
    protected
      procedure OnWMHScroll(var Message : TMessage); message WM_HSCROLL;
      procedure OnWMVScroll(var Message : TMessage); message WM_VSCROLL;

    public
      SyncWithRichEdit : TRichEdit;
  end;

procedure Register;

implementation

{ TMyRichEdit }

procedure TMyRichEdit.OnWMHScroll(var Message: TMessage);
begin
  SendMessage(SyncWithRichEdit.Handle, WM_HSCROLL, Message.WParam, Message.LParam);
end;

procedure Register;

begin
  RegisterComponents('Samples', [TMyRichEdit]);
end;

procedure TMyRichEdit.OnWMVScroll(var Message: TMessage);
begin
 SendMessage(SyncWithRichEdit.Handle, WM_VSCROLL, Message.WParam, Message.LParam);
 inherited;
end;

end.

Except there isn't a EM_SETFIRSTVISIBLELINE so you can't do

  RichEdit1.Perform(EM_SETFIRSTVISIBLELINE,
  Perform(EM_GETFIRSTVISIBLELINE, 0, 0));

sigh.

Raymond.
I tried this in the on change but jut moving the cursor does not generate an onchange...

Cheers,

Raymond

  if Richedit1.Perform(EM_GETFIRSTVISIBLELINE, 0, 0) >
     MyRichEdit1.Perform(EM_GETFIRSTVISIBLELINE, 0, 0) then
    MyRichEdit1.perform(em_scroll, SB_LINEDOWN, 0)
  else
    MyRichEdit1.perform(em_scroll, SB_LINEUP, 0);
ASKER CERTIFIED SOLUTION
Avatar of rwilson032697
rwilson032697

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Eureka! Here 'tis: A complete solution...

Cheers,

Raymond.

//************************* Source for the TMyRichEdit component...

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls;

type
  TMyRichEdit = class(TRichEdit)
    protected
      procedure OnWMHScroll(var Message : TMessage); message WM_HSCROLL;
      procedure OnWMVScroll(var Message : TMessage); message WM_VSCROLL;
      procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
    public
      SyncWithRichEdit : TRichEdit;
  end;

procedure Register;

implementation

uses
  RichEdit;

{ TMyRichEdit }

procedure TMyRichEdit.OnWMHScroll(var Message: TMessage);
begin
  SendMessage(SyncWithRichEdit.Handle, WM_HSCROLL, Message.WParam, Message.LParam);
end;

procedure TMyRichEdit.OnWMVScroll(var Message: TMessage);
begin
 SendMessage(SyncWithRichEdit.Handle, WM_VSCROLL, Message.WParam, Message.LParam);
 inherited;
end;

procedure TMyRichEdit.CNNotify(var Message: TWMNotify);
var
  Diff : Integer;
  c : integer;
begin
  Inherited;
  with Message do
    case NMHdr^.code of
      EN_SELCHANGE:
      begin
        Diff := SyncWithRichEdit.Perform(EM_GETFIRSTVISIBLELINE, 0, 0) -
                 Perform(EM_GETFIRSTVISIBLELINE, 0, 0);
        c := abs(diff);
        while c > 0 do
          begin
            if diff < 0 then
              SyncWithRichEdit.perform(em_scroll, SB_LINEDOWN, 0)
             else
              SyncWithRichEdit.perform(em_scroll, SB_LINEUP, 0);
            dec(c);
          end;
      end;
    end;
end;


procedure Register;

begin
  RegisterComponents('Samples', [TMyRichEdit]);
end;

end.

//************************* Form to test it with - just put a TRichEdit and a TMyRichEdit on it
unit RicheditForm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls, Unit1;

type
  TForm1 = class(TForm)
    RichEdit1: TRichEdit;
    MyRichEdit1: TMyRichEdit;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  MyRichEdit1.SyncWithRichEdit := RichEdit1;
end;


BRILLIANT!
Thank you Raymond...this looks a great solution.
Just when I thought there was not solution you found one..

Thanks again.
Dave