• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2156
  • Last Modified:

displaying current cursor position on status bar

Hi,

I am creating editor based on TSynMemo component from SynEdit suite. This component is similar to TMemo. I would like to write current row/column on status bar. To do so I have to put code in many, many places (OnKeyUp, OnClicked etc.) and it still doesn't work as expected in some situations. In TRichEdit control there's OnSelectionChange event which is best for such activity. Unfortunately neither in TSynMemo nor in TMemo this event exists. So my question - what is the best way to catch row/column (or SelStart) while editing text in TMemo.

Albi
0
albireo77
Asked:
albireo77
1 Solution
 
robert_marquardtCommented:
You could subclass the window and trigger to the EM_SETSEL message which sets the caret (that is what you are talking about).
0
 
ZhaawZSoftware DeveloperCommented:
nope, processing em_setsel does not work with TMemo (i.e., this message is not sent to TMemo when user "manually" sets cursor pos / selection)
0
 
Slick812Commented:
hello albireo77, , I do not remember  an API message for and mutiline edit to happen foe a claret change position?
Anyway, here is some code that can read out the claret position for a TMemo


procedure TForm2.SetLineNum;
var
MesRe, ChPos, Line: Integer;
begin // this gets the position and does a Label1 caption for claret position
MesRe := Memo1.Perform(EM_GETSEL, 0, 0);
ChPos := HIWORD(MesRe);
Line := Memo1.Perform(EM_LINEFROMCHAR, ChPos, 0);
MesRe := Memo1.Perform(EM_LINEINDEX, Line, 0);
if MesRe < 0 then
  Label1.Caption := '0:0'
  else
  Label1.Caption := IntToStr(Line+1)+' : '+IntToStr(1+ChPos - MesRe);
end;

procedure TForm2.Memo1Change(Sender: TObject);
begin // TMemo OnChange event
SetLineNum;
end;

procedure TForm2.Memo1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin  // OnMouseUp event
SetLineNum;
end;

procedure TForm2.Memo1KeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin // OnKeyUp event
if Key in [VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT, VK_HOME, VK_END] then
  SetLineNum;
end;

 = = = = = = = = = = = = = = = = = =

this seems to work for me, but there may be other way to change the memo, that is not coded for here.
ask questions if you need more information
0
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
ZhaawZSoftware DeveloperCommented:
About Slick812's SetLineNum - there's a TMemo().CaretPos that could be used to get "current caret position" - it could be a shorter way than sending those messages...
0
 
robert_marquardtCommented:
EM_SETSEL must be sent. TMemo.CaretPos uses it in its implementation.
0
 
HillGrooverCommented:
You could always try the OnStatusChange event, it's always worked fine for me

procedure TForm1.SynMemo1StatusChange(Sender: TObject; Changes: TSynStatusChanges);
var
   p: TPoint;
begin
   if Changes * [scAll, scCaretX, scCaretY] <> [] then
      begin
         p := (Sender as TSynMemo).CaretXY;
         StatusBar1.SimpleText := Format('%6d:%3d', [p.Y, p.X]);
      end;
end;
0
 
ZhaawZSoftware DeveloperCommented:
robert_marquardt, it uses em_setsel when setting caret position, not getting..


property CaretPos: TPoint read GetCaretPos write SetCaretPos;

function TCustomMemo.GetCaretPos: TPoint;
begin
  Result.X := LongRec(SendMessage(Handle, EM_GETSEL, 0, 0)).Hi;
  Result.Y := SendMessage(Handle, EM_LINEFROMCHAR, Result.X, 0);
  Result.X := Result.X - SendMessage(Handle, EM_LINEINDEX, -1, 0);
end;

procedure TCustomMemo.SetCaretPos(const Value: TPoint);
var
  CharIdx: Integer;
begin
  CharIdx := SendMessage(Handle, EM_LINEINDEX, Value.y, 0) + Value.x;
  SendMessage(Handle, EM_SETSEL, CharIdx, CharIdx);
end;



What I wanted to say in my 1st post was that TMemo does not receive em_setsel each time when selection changes. However, it's possible to set selection with em_setsel, but it does not matter this time.
0
 
HardiCommented:
TMemoBar can be attached to a T(Custom)Memo component to provide additional info/functionality for a Memo component, including the current location (row and column) of the caret (textual cursor)

http://delphi.about.com/library/weekly/aa083005a.htm
0
 
robert_marquardtCommented:
The TMemo probably does not receive the EM_SETSEL because it is sent to the Windows control TMemo uses.
I meant to subclass that window to catch the EM_SETSEL sent to it. The caret is probably only set via that message. The control sends this message probably also to itself.
You have found a solution so i just want to clarify this.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now