Recent

Author Topic: how to get line number of text under mouse.position  (Read 2959 times)

Josh

  • Hero Member
  • *****
  • Posts: 1344
how to get line number of text under mouse.position
« on: June 19, 2023, 06:59:34 pm »
Hi

Is it possible to get the line number of the text under the current mouse location; without modifying the caret position.

Ideally without having the synedit as active control,

Am trying to analyze contents of multiple synedit by just moving the mouse over the text, without selecting any.

At the moment am using applicationproperties.onuserinput to intercept mouse movement and detect the control under cursor position.

Code: Pascal  [Select][+][-]
  1. var Msg: Cardinal);
  2.       cntrl:TControl;
  3. begin
  4.   if msg<>LM_MOUSEMOVE then exit;
  5.   cntrl:= FindLCLControl(mouse.CursorPos);
  6.   if cntrl is TSynEdit then
  7.   begin
  8.      ..
  9.    // ctrl under mouse is tsynedit
  10.   end                    
« Last Edit: June 19, 2023, 07:02:46 pm by Josh »
The best way to get accurate information on the forum is to post something wrong and wait for corrections.

DomingoGP

  • Jr. Member
  • **
  • Posts: 80
Re: how to get line number of text under mouse.position
« Reply #1 on: June 19, 2023, 08:35:54 pm »
Hi,

Maybe this code works for you.

Regards
Domingo.

Code: Pascal  [Select][+][-]
  1. uses
  2.   lmessages, SynEditTypes;
  3.  
  4. procedure TForm1.OnUserInputEvent(Sender: TObject; Msg: cardinal);
  5. var
  6.   cntrl: TControl;
  7.   cntrlPos: TPoint;
  8.   rowColumn: TPoint;
  9. begin
  10.   if msg <> LM_MOUSEMOVE then exit;
  11.   cntrl := FindLCLControl(mouse.CursorPos);
  12.   if cntrl is TSynEdit then
  13.   begin
  14.     cntrlPos := cntrl.ScreenToControl(mouse.CursorPos);
  15.     rowColumn := TSynEdit(cntrl).PixelsToRowColumn(cntrlPos, [scmIncludePartVisible]);
  16.     if rowColumn.Y <= TSynEdit(cntrl).Lines.Count then
  17.       Label1.Caption := 'Line: ' + IntToStr(rowColumn.Y)
  18.     else
  19.       Label1.Caption := '';
  20.   end
  21.   else
  22.     label1.Caption := '';
  23. end;
  24.  

Josh

  • Hero Member
  • *****
  • Posts: 1344
Re: how to get line number of text under mouse.position
« Reply #2 on: June 19, 2023, 10:17:23 pm »
Hi DomingoGP

Thanks that had the info needed.  :)

First time i've used SynEdit so probably have more questions.

Code: Pascal  [Select][+][-]
  1. var Msg: Cardinal);
  2.       cntrl:TControl;
  3.       LineUnderMouse:AnsiString='';
  4. begin
  5.   if msg<>LM_MOUSEMOVE then exit;
  6.   cntrl:= FindLCLControl(mouse.CursorPos);
  7.   if cntrl is TSynEdit then
  8.   begin
  9.     // ctrl under mouse is tsynedit
  10.     LineUnderMouse:=TSynEdit(cntrl).Lines[(tpoint(TSynEdit(cntrl).PixelsToRowColumn(tpoint(cntrl.ScreenToControl(mouse.CursorPos)),[scmIncludePartVisible])).Y)-1]);
  11.   end;            

Thanks
« Last Edit: June 19, 2023, 10:19:23 pm by Josh »
The best way to get accurate information on the forum is to post something wrong and wait for corrections.

DomingoGP

  • Jr. Member
  • **
  • Posts: 80
Re: how to get line number of text under mouse.position
« Reply #3 on: June 19, 2023, 10:55:55 pm »
You are welcome.

You should check that the line is not greater than TSynEdit(cntrl).lines.count.

For example if the editor has only 2 lines of text and you move the cursor below the second line it will fail when you access TSynEdit(cntrl).lines[3].

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 10547
  • Debugger - SynEdit - and more
    • wiki
Re: how to get line number of text under mouse.position
« Reply #4 on: June 19, 2023, 11:38:16 pm »
From SynEdit
Code: Pascal  [Select][+][-]
  1.     // Pixel
  2.     function ScreenColumnToXValue(Col: integer): integer;  // map screen column to screen pixel
  3.     function ScreenXYToPixels(RowCol: TPhysPoint): TPoint; // converts screen position (1,1) based
  4.     function RowColumnToPixels(RowCol: TPoint): TPoint; // deprecated 'use ScreenXYToPixels(TextXYToScreenXY(point))';
  5.     function PixelsToRowColumn(Pixels: TPoint; aFlags: TSynCoordinateMappingFlags = [scmLimitToLines]): TPoint;
  6.     function PixelsToLogicalPos(const Pixels: TPoint): TPoint;
  7.     //
  8.     function ScreenRowToRow(ScreenRow: integer; LimitToLines: Boolean = True): integer; override; deprecated 'use ScreenXYToTextXY';
  9.     function RowToScreenRow(PhysicalRow: integer): integer; override; deprecated 'use TextXYToScreenXY';
  10.     (* ScreenXY:
  11.        First visible (scrolled in) screen line is 1
  12.        First column is 1 => column does not take scrolling into account
  13.     *)
  14.     function ScreenXYToTextXY(AScreenXY: TPhysPoint; LimitToLines: Boolean = True): TPhysPoint; override;
  15.     function TextXYToScreenXY(APhysTextXY: TPhysPoint): TPhysPoint; override;
  16.  

Logical/Physical https://wiki.freepascal.org/SynEdit#Logical.2FPhysical_caret_position

You could use the PixelsTO.... function

PixelsToRowColumn is physical.
PixelsToLogicalPos is the byte in the line text.

Josh

  • Hero Member
  • *****
  • Posts: 1344
Re: how to get line number of text under mouse.position
« Reply #5 on: June 19, 2023, 11:40:05 pm »
Hi

I had to use Y-1 to get the actual line.

I have tested with 2/3 line synedit as well as 0 line and it returns as expected no bang, unless i am missing something.

But i think a safety/sanity check woud be wise..
The best way to get accurate information on the forum is to post something wrong and wait for corrections.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 10547
  • Debugger - SynEdit - and more
    • wiki
Re: how to get line number of text under mouse.position
« Reply #6 on: June 19, 2023, 11:44:36 pm »
Hi

I had to use Y-1 to get the actual line.

I have tested with 2/3 line synedit as well as 0 line and it returns as expected no bang, unless i am missing something.

But i think a safety/sanity check woud be wise..

You mean it returns non existing lines? => scmLimitToLines ?

Josh

  • Hero Member
  • *****
  • Posts: 1344
Re: how to get line number of text under mouse.position
« Reply #7 on: June 19, 2023, 11:45:46 pm »
Hi Martin_fr,

when i was testing ideas, i tried a few of those, but they are based on the position of the caret in synedit, unless i done something wrong of course.

it was giving me the line after the one i was after, so i thought it was something to do with one function being non zero based.

did not check too much, but it solved the issue.
« Last Edit: June 19, 2023, 11:47:57 pm by Josh »
The best way to get accurate information on the forum is to post something wrong and wait for corrections.

Josh

  • Hero Member
  • *****
  • Posts: 1344
Re: how to get line number of text under mouse.position
« Reply #8 on: June 20, 2023, 12:10:41 am »
Just added test proj that demonstrates

« Last Edit: June 20, 2023, 12:24:27 am by Josh »
The best way to get accurate information on the forum is to post something wrong and wait for corrections.

DomingoGP

  • Jr. Member
  • **
  • Posts: 80
Re: how to get line number of text under mouse.position
« Reply #9 on: June 20, 2023, 12:35:37 am »
Quote
You mean it returns non existing lines? => scmLimitToLines ?

The code I have suggested uses [scmIncludePartVisible] which allows to detect if the cursor is below the last text line if we compare the returned row with lines.count.

Quote
I have tested with 2/3 line synedit as well as 0 line and it returns as expected no bang, unless i am missing something.

You are right  Synedit1.Lines[10000] returns an empty string without any error.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 10547
  • Debugger - SynEdit - and more
    • wiki
Re: how to get line number of text under mouse.position
« Reply #10 on: June 20, 2023, 01:04:11 am »
when i was testing ideas, i tried a few of those, but they are based on the position of the caret in synedit, unless i done something wrong of course.

None of them should interact with or require the caret.

Pixels => as in mouse, but afaik must be relative to cilentrect.

ScreenXy => text coordinates in the window, but without scrolling => the visible "grid" => top corner is always 1,1

TextXy => (IIRC) physical coordinates in the text.

Quote
it was giving me the line after the one i was after, so i thought it was something to do with one function being non zero based.

Those functions are IIRC all 1 based.
The SynEdit.Lines[] property is 0 based.
The carte and SynEdit.LeftChar => 1 based
TopLine... I have to check...

If you look at the sources
- SomeVal: IntIdx; => 0 based (index)
- SomeVal: IntPos; => 1 based (position)
But not everything already has those types.

 

TinyPortal © 2005-2018