Recent

Author Topic: [Solved] Memo on wordwarp event  (Read 4519 times)

lazdeveloper

  • Jr. Member
  • **
  • Posts: 61
Re: Memo on wordwarp event
« Reply #15 on: April 18, 2020, 01:44:47 pm »
I guess there a point lost here. Fortes report offeres it's own visual components that you can see and use on the main report component.
Given this, simply you cannot use listbox on the report since it will take you to another unexpected behaviour since listbox is not one of the report set. Please have a look at Fortes report to see the point further.

Cheers

jamie

  • Hero Member
  • *****
  • Posts: 7523
Re: Memo on wordwarp event
« Reply #16 on: April 18, 2020, 01:59:00 pm »
No, you can still use a Tmemo but you don't  understand what I laid out so I'll just withdraw from this and hope one day  you'll see the light from where you sit.

Maybe someone else can help you.
The only true wisdom is knowing you know nothing

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Memo on wordwarp event
« Reply #17 on: April 18, 2020, 02:31:24 pm »
Hi!

Again and again and again:

If you want to have control about the line numbers then

disable WordWrap

Or use another component.

Winni

lucamar

  • Hero Member
  • *****
  • Posts: 4217
Re: Memo on wordwarp event
« Reply #18 on: April 18, 2020, 04:41:06 pm »
I think the OP's isn't talking about TMemo but about TFRMemo, the similar control from Fortes Report.

To the OP:
I don't how similar they are to each other but if FR's derives from the standard one then everything said here applies: unless the folks at Fortes have done something to correct it, in some platforms Lines.Count return the number of visible lines rather than the number of "real" lines (paragraphs, if you will); and worse: that behaviour is platform dependent, so programs compiled for, say, Windows vs. Linux behave differently.

And because (again, unless a workaround is applied in the derived class) it's implemented by the OS there is no easy, cross-platform way to add a callback for each line that gets wrapped.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

lazdeveloper

  • Jr. Member
  • **
  • Posts: 61
Re: Memo on wordwarp event
« Reply #19 on: April 18, 2020, 05:09:08 pm »
Thank you all.
Lucamar you are right.. the TRLMemo of fortes is implemented in RLRepot.pas at
https://github.com/fortesinformatica/fortesreport-ce/blob/master/Source/RLReport.pas

Ofcourse it inherits from an ancesstor class. However if you look at the implementation of the function RunMemo taken from the RLReport.pas given up
Code: Pascal  [Select][+][-]
  1. procedure RunMemo(const Buffer: string; Canvas: TObject;
  2.   Alignment: TRLTextAlignment; const ARect: TRect; MaxWidth, MaxHeight: Integer;
  3.   var Size: TPoint);
  4. var
  5.   LineHeight: Integer;
  6.   LineWidth: Integer;
  7.   LineOffset: Integer;
  8.   Pos: Integer;
  9.   Wrapped: Boolean;
  10.   TextLn: string;
  11.   Aux: TRect;
  12.   LineAlign: TRLTextAlignment;
  13. begin
  14.   Size.X := 0;
  15.   LineHeight := CanvasTextHeight(Canvas, 'A');
  16.   LineOffset := 0;
  17.   Pos := 1;
  18.   while Pos <= Length(Buffer) do
  19.   begin
  20.     TextLn := NextLine(Buffer, Pos, Wrapped, LineWidth, Canvas, MaxWidth);
  21.     if LineWidth > Size.X then
  22.       Size.X := LineWidth;
  23.     Aux := Rect(ARect.Left + 0, ARect.Top + LineOffset, ARect.Left +
  24.       MaxWidth, ARect.Top + LineOffset + LineHeight);
  25.     if Aux.Bottom > ARect.Bottom then
  26.       Aux.Bottom := ARect.Bottom;
  27.     LineAlign := Alignment;
  28.     if (LineAlign = taJustify) and not Wrapped then
  29.       LineAlign := taLeftJustify;
  30.     CanvasTextRect(Canvas, Aux, TextLn, LineAlign);
  31.     Inc(LineOffset, LineHeight);
  32.     if LineOffset > MaxHeight then
  33.       Break;
  34.   end;
  35.   Size.Y := LineOffset;
  36. end;
  37.  

Here I am trying to find a footstep to get the lines that are wrapped

lucamar

  • Hero Member
  • *****
  • Posts: 4217
Re: Memo on wordwarp event
« Reply #20 on: April 18, 2020, 06:30:26 pm »
It's difficult to say without studying more carefully the whole implementation but I making the marked additions should probably do (almost) what you want:

Code: Pascal  [Select][+][-]
  1. type
  2.   TWrapLineEvent = procedure(const Position: Integer);
  3.  
  4. procedure RunMemo(const Buffer: string; Canvas: TObject;
  5.   Alignment: TRLTextAlignment; const ARect: TRect; MaxWidth, MaxHeight: Integer;
  6.   var Size: TPoint;
  7.   OnWrapLine: TWrapLineEvent = nil);
  8. var
  9.   LineHeight: Integer;
  10.   LineWidth: Integer;
  11.   LineOffset: Integer;
  12.   Pos: Integer;
  13.   Wrapped: Boolean;
  14.   TextLn: string;
  15.   Aux: TRect;
  16.   LineAlign: TRLTextAlignment;
  17. begin
  18.   Size.X := 0;
  19.   LineHeight := CanvasTextHeight(Canvas, 'A');
  20.   LineOffset := 0;
  21.   Pos := 1;
  22.   while Pos <= Length(Buffer) do
  23.   begin
  24.     TextLn := NextLine(Buffer, Pos, Wrapped, LineWidth, Canvas, MaxWidth);
  25.     if Wrapped and Assigned(OnWrapLine) then
  26.        OnWrapLine(Pos);
  27.     if LineWidth > Size.X then
  28.       Size.X := LineWidth;
  29.     Aux := Rect(ARect.Left + 0, ARect.Top + LineOffset, ARect.Left +
  30.       MaxWidth, ARect.Top + LineOffset + LineHeight);
  31.     if Aux.Bottom > ARect.Bottom then
  32.       Aux.Bottom := ARect.Bottom;
  33.     LineAlign := Alignment;
  34.     if (LineAlign = taJustify) and not Wrapped then
  35.       LineAlign := taLeftJustify;
  36.     CanvasTextRect(Canvas, Aux, TextLn, LineAlign);
  37.     Inc(LineOffset, LineHeight);
  38.     if LineOffset > MaxHeight then
  39.       Break;
  40.   end;
  41.   Size.Y := LineOffset;
  42. end;
« Last Edit: April 18, 2020, 06:32:03 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

lazdeveloper

  • Jr. Member
  • **
  • Posts: 61
Re: Memo on wordwarp event
« Reply #21 on: April 18, 2020, 08:31:40 pm »
Cheers lucamar.

Will try it out.

Many thanks

lazdeveloper

  • Jr. Member
  • **
  • Posts: 61
Re: Memo on wordwarp event
« Reply #22 on: April 20, 2020, 01:33:06 am »
Finally the solution was to call the lines.count method
Code: Pascal  [Select][+][-]
  1. I:= Memo1.lines.count;
  2. // you must have the form that the memo on it visible for the method to work
  3. // or else it will give you wrong value
  4.  
  5.  
It seems that there are some issues with this method see for example

https://forum.lazarus.freepascal.org/index.php?topic=26914.0

And this as well

https://forum.lazarus.freepascal.org/index.php/topic,25763.0.html

However, under win10 it works perfect.

Thank you all for your contributions.
« Last Edit: April 20, 2020, 01:00:23 pm by lazdeveloper »

jamie

  • Hero Member
  • *****
  • Posts: 7523
Re: [Solved] Memo on wordwarp event
« Reply #23 on: April 20, 2020, 02:01:33 am »
There is a way to determine if the Text has wrapped on the screen..

What you need to do is scan the screen vertically using two windows control messages..

EM_CHARFROMPOS;
 
  That returns the Index of a character within the buffer using the X,Y plot on the memo's canvas.

From that, you do this.

EM_LINEFROMCHAR;

That will return the line number.

So lets say the font size you are using requires 16 pixels per line, now you know you need to increment 16 times per line number that gives you the Y axes.. X would be 0 I guess.

 So if you have lets say line 1 and 2 displaying the same line internally because it got wrapped around the end results will report line 2 as line 1 . this is how you can determine if the lines are wrapped.

 Its a two step process using two messages via the SendMessage(Memo.Handle, WM_CHARFROMPOS,0 @POintStructureHoldingTheXandY);

The return is the location in the buffer and from that value you can get the line number..

etc..
 I could make up a working example...

The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 7523
Re: [Solved] Memo on wordwarp event
« Reply #24 on: April 20, 2020, 03:19:38 am »
This little example will report to you the actual internal line number in the buffer when you move your mouse over the memo. so if you have lines that are wrapping this will report the actual line number they belong to in the buffer.
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Memo1MouseMove(Sender: TObject; Shift: TShiftState; X,
  2.   Y: Integer);
  3. var
  4.   CSP,L,R:Integer;
  5.   S:String;
  6. begin
  7.   WIth Tmemo(Sender)do
  8.    Begin
  9.      R := SendMessage(Handle, EM_CHARFROMPOS,0,MAKELPARAM(X,Y));
  10.      S := Lines.Text;
  11.      L := 1;
  12.      CSP:= 0;
  13.      {Character index in buffer sits in the lower WORD}
  14.      IF SmallInt(R) <> -1 Then
  15.      While (S[L]<>#0)and(L< WOrd(R)) do
  16.      Begin
  17.        If S[L] in [#13,#10] Then {Skip Line endings}
  18.         Begin
  19.           Inc(CSP); // Line number count;
  20.           If (S[L]<> S[L+1])And(S[L+1] in [#13,#10]) Then inc(L);
  21.         end;
  22.          Inc(L);
  23.      End;
  24.      Form1.Caption := 'Line Numner :'+CSP.Tostring;
  25.      end;
  26.    end;
  27.  

 You can all this directly via a method supplying a X, Y to determine which lines on the memo are showing which lines in the buffer.

 The Y axes can be multiplied times the height of  your text//
Use the Canvas for that.
Y := LineNUmberOFInterest*Canvas.TextHeight('H');
X could be 0;
But first you can see how the values resolve using the mouse..

Make sure you have some long lines in there so you can get wraps

« Last Edit: April 20, 2020, 03:21:09 am by jamie »
The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018