Recent

Author Topic: LzRichEdit -How to Scroll editors in paralell, - How to set background color  (Read 10313 times)

arneolav

  • Full Member
  • ***
  • Posts: 197
Hi!   I'm using win XP, Lazarus 1.2.RC1, FPC2.6.2

I'm moving a language translating system from Delphi, DevExpress and JEDI) to Lazarus.
A dictonary is stored in Dbf and updated in Lazarus DbGrid.

The exRichEdit example is used as a base, and supported wih a second editor.
I'v have tried som other editors, but LzRichEdit seems to be the best RichEdit with Lazarus.
Thanx to the editor of LzRichEdit !!!!
....

In this system, two LzRichEdit's are used in paralell:
Text in the left RichEdit is scanned, translated, and the result is displayed in the right editor.
The user can modify the text in the left editor and do a new translation or,
do the last modificationes in the right editor or/and save to file or copy to another editor (word)

Most of the work is now done, but I'v 2 problems

1)Scroll editors in paralell in LzRichEdit
2)Set alternativ background color i marked text  in LzRichEdit
(See picture)


1) Scroll editors in paralell in LzRichEdit:
The vertical scollBar in the left (Editor1) should move the right (Editor2) in paralell with Editor1.

This codesnip from  Delphi  don't compile in Lazarus:
Code: [Select]
private
         PRichEdWndProc, POldWndProc: Pointer;              {Scroll editors}
      procedure RichEdWndProc(var Msg: TMessage);    {Scroll editors}

.....

In  FormCreate:
    PRichEdWndProc := MakeObjectInstance(RichEdWndProc);    <-------------------------- error, missing parameter
    POldWndProc       := Pointer(SetWindowLong(RichEditor1.Handle, GWL_WNDPROC,
                                                         Integer(PRichEdWndProc)));
.....

procedure Form1.RichEdWndProc(var Msg: TMessage);
begin
  Msg.Result := CallWindowProc(POldWndProc, RichEditor1.Handle, Msg.Msg,
                                                Msg.wParam, Msg.lParam);

  if (Msg.Msg = WM_VSCROLL) and (LOWORD(Msg.wParam) = SB_THUMBTRACK) then
  begin
     RichEditor2.Perform(Msg.Msg, Msg.wParam, Msg.lParam);
      SetScrollPos (RichEditor2.Handle, SB_VERT, HIWORD(Msg.wParam), True);
  end;
end;

....................

2) Set alternativ backround color in marked text   (as Mark color)
In Delphi /JvRichEdit   :   
    Editor.SelStart     := iMarkStart;
    Editor.SelLength := iMarkLen;
    Editor.SelAttributes.Color          :=  clBlack
    Editor.SelAttributes.BackColor := clYellow
    Editor.SelLength := 0;
   
   I think this could be done by canvas color but need some ideas.   


When this two cases are solved the system is more or less as the in Delphi/DevExpress.
« Last Edit: December 17, 2013, 11:11:05 pm by arneolav »
Win 11, win64 , Lazarus 4.0RC3
Delphi/DevExpress

howardpc

  • Hero Member
  • *****
  • Posts: 4144
This just addresses your first problem.
It is a hack rather than a solution to your problem, however the following code shows how you might be able to use the application's Idle event to do synchronisation between the two richedit's scrolling.
The solution, of course, is to find a reliable cross-platform way to be notified of a richedit's scroll events and respond by mirroring the event to a second control.

Code: [Select]
unit mainSync;

{$mode objfpc}{$H+}

interface

uses
  Classes, Forms, RichBox, LCLType, LCLIntf;

type

  { TForm1 }

  TForm1 = class(TForm)
    LeftRE: TlzRichEdit;
    RightRE: TlzRichEdit;
    procedure FormCreate(Sender: TObject);
  private
    originalLeftREPos: integer;
    procedure SBIdleHandler(Sender: TObject; var Done: boolean);
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.OnIdle:=@SBIdleHandler;
end;

procedure TForm1.SBIdleHandler(Sender: TObject; var Done: boolean);
var
  newPos, diff: integer;
  rct: tRect;
begin
  if not Assigned(LeftRE) or not Assigned(RightRE) then
    Exit;
  rct:=RightRE.ClientRect;
  newPos:=LeftRE.VertScrollBar.Position;
  if newPos<>originalLeftREPos then begin
    diff:=newPos - originalLeftREPos;
    ScrollWindowEx(RightRE.Handle,0,diff,@rct,@rct,0,nil,SW_INVALIDATE);
    RightRE.VertScrollBar.Position:=newPos;
    originalLeftREPos:=newPos;
  end;
  Done:=True;
end;

end.             

arneolav

  • Full Member
  • ***
  • Posts: 197
Thanx' a lot!
I got the idea, but cant get it work perfect;

First, the text-move was opposite so I had to change the line:
From: diff:=newPos - originalLeftREPos;
To:     diff:= originalLeftREPos - newPos;

Then the upper part of the text is scrolling ok, but the lowerpart is coruppted.
Suppose this has something to do with the rect; seems as size oft the rect is too small (?)

....
Besides, the scroll apperas on mouse up, not as in Delphi (shown above) in realtime.
May be this could be done with use of a timer instead of on Application.OnIdle?
Win 11, win64 , Lazarus 4.0RC3
Delphi/DevExpress

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Yes, idle events are not immediate, so it's not a proper solution.
A timer might slightly improve the responsiveness, but really you need the Lazarus equivalent of hooking a window procedure. Maybe one of the developers can show us how.
There are three rects involved in the ScrollWindowEx call, and I lazily set one to nil, which may account for the corruption.

engkin

  • Hero Member
  • *****
  • Posts: 3112
Assuming your original code really works on Delphi, your problem seems in:
Code: [Select]
    PRichEdWndProc := MakeObjectInstance(RichEdWndProc);    <-------------------------- error, missing parameter

Pass @RichEdWndProc instead of RichEdWndProc.

Anyway I doubt that it works without more changes.

I don't have LzRichEdit but I assume the following should work:

Code: [Select]
//add these to your form
public
    OrgMemoWndProc: TWndMethod;
    procedure MemoWndMethod(var TheMessage: TLMessage);


change the WindowProc of your RichEditor1:

Code: [Select]
//in your form OnCreate, maybe
  OrgMemoWndProc := RichEditor1.WindowProc;
  RichEditor1.WindowProc := @MemoWndMethod;

and here is the real work:

Code: [Select]
procedure TForm1.MemoWndMethod(var TheMessage: TLMessage);
begin
  OrgMemoWndProc(TheMessage);
  if TheMessage.msg = LM_VSCROLL then
  begin
    SendMessage(RichEditor2.Handle, WM_VSCROLL, TheMessage.wParam, TheMessage.lParam);
  end;
end;

You might need to add LMessages and lcltype to your uses:

arneolav

  • Full Member
  • ***
  • Posts: 197
Thanx engkin,

The texts in two editors are scrolling perfect inline.
but... the right scrollbar dosen't move until on MouseUp ..Just a minor problem.

This may be to help for others so i put a complet demo-code here:

Drop two LzRichEditors on a form.   (May be ok in other RichEditors too)
Put in Uses: Windows, LMessages
Code: [Select]
unit Unit1;

{$mode objfpc}{$H+}

interface

uses      Windows,
   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, lzRichEdit,
   LMessages; 

type

  { TForm1 }

  TForm1 = class(TForm)
    lzRichEdit1: TlzRichEdit;
    lzRichEdit2: TlzRichEdit;

    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
      OrgMemoWndProc: TWndMethod;
    procedure MemoWndMethod(var TheMessage: TLMessage);
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  OrgMemoWndProc := lzRichEdit1.WindowProc;
  lzRichEdit1.WindowProc := @MemoWndMethod
end;

procedure TForm1.MemoWndMethod(var TheMessage: TLMessage);
begin
  OrgMemoWndProc1(TheMessage);
  if TheMessage.msg = LM_VSCROLL then
    SendMessage(lzRichEdit2.Handle, WM_VSCROLL, TheMessage.wParam, TheMessage.lParam);

  if TheMessage.wParamlo = SB_THUMBTRACK then
    SetScrollPos(lzRichEdit2.Handle, SB_VERT, TheMessage.wParamhi, True);
end;
end. 


......
And, yes, the Delphi-code is just as shown abow, compiles and run ok. Has been in use a lot of years.
But with the ....  @RichEdWndProc ... does not compile in Lazarus ..
main.pas(302,43) Error: Incompatible type for arg no. 1: Got "Pointer", expected "<procedure variable type of function(LongWord,LongWord,LongInt,LongInt):LongInt;StdCall>"
Not important, ...
« Last Edit: December 18, 2013, 06:18:26 pm by arneolav »
Win 11, win64 , Lazarus 4.0RC3
Delphi/DevExpress

engkin

  • Hero Member
  • *****
  • Posts: 3112
but... the right scrollbar dosen't move until on MouseUp ..Just a minor problem.
I tried it on TMemo and that's not the case. Maybe just TLzRichEdit. Try to tell the scroll bar to move. For instance:

Code: [Select]
  if TheMessage.wParamlo = SB_THUMBTRACK then
    SetScrollPos(lzRichEdit2.Handle, SB_VERT, TheMessage.wParamhi, True);

arneolav

  • Full Member
  • ***
  • Posts: 197
That did the trick,
Demo-code over is modified.
Thanx! Now, scroll is perfect!
Win 11, win64 , Lazarus 4.0RC3
Delphi/DevExpress

engkin

  • Hero Member
  • *****
  • Posts: 3112
Just to let you know that your code should compile if you use Delphi mode. By default, Lazarus creates projects with OBJFPC mode, to select a different compiler mode change {$mode xxxx} at the top of your file. Delphi mode for instance:

Code: [Select]
unit YourUnitName;

{$mode delphi}
...

I don't know if it's going to work as you expect but it should compile.
« Last Edit: December 19, 2013, 02:38:51 am by engkin »

arneolav

  • Full Member
  • ***
  • Posts: 197
Yes, it does compile in Delphi mode {$MODE Delphi}
But; the text in right editor is not moved, only the scrollbar.

Does not matter, I prefere your solution, its more clear Lazarus and more simple,

But.. interesting testing, thanks for the idea.

Win 11, win64 , Lazarus 4.0RC3
Delphi/DevExpress

 

TinyPortal © 2005-2018