LzRichEdit -How to Scroll editors in paralell, - How to set background color lazarus / 5-Lazarus Extra Components ---------------------------------------------------------------------- arneolav · 2013-12-17 18:34 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. ---------------------------------------------------------------------- howardpc · 2013-12-18 09:11 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 · 2013-12-18 14:26 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? ---------------------------------------------------------------------- howardpc · 2013-12-18 15:26 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 · 2013-12-18 15:35 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 · 2013-12-18 16:40 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 "" Not important, ... ---------------------------------------------------------------------- engkin · 2013-12-18 17:12 Quote from: arneolav on December 18, 2013, 05:40:10 pmbut... 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 · 2013-12-18 17:19 That did the trick, Demo-code over is modified. Thanx! Now, scroll is perfect! ---------------------------------------------------------------------- engkin · 2013-12-19 01:08 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. ---------------------------------------------------------------------- arneolav · 2013-12-19 18:50 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.