When you have a TStringGrid with the goEditing option set and a cell has several lines of text in it, when you go to edit that cell by clicking on it, the cursor will be at the very end of that text. How can you move the cursor to another position? My particular problem is that if the text has a carriage return at the end, the user thinks the cell is empty. I'd like to move the cursor before any carriage returns.
Asked
Active
Viewed 2,957 times
1
-
You could try getting a hold of the Editor control and doing a SelectAll after the click, of the in place editor (not the main grid) – Warren P Sep 20 '16 at 19:51
2 Answers
4
Rather than trying to manipulate the editor's cursor, I would suggest trying to avoid storing trailing line breaks in the StringGrid to begin with. You can use the OnGetEditText
event to trim off the trailing line breaks when the editor is activated, and the OnSetEditText
event to trim them off when the user enters new text.

Remy Lebeau
- 555,201
- 31
- 458
- 770
4
Assuming you are using the VCL, InplaceEditor
is a property of TCustomGrid
. It is of type TInplaceEdit
which descents from TCustomEdit
. You can move the cursor inside of it Just like a TEdit
.
If you are using the automatic way of editing the content of the cell, you can use the following way to move the cursor. I have tested it and it works for me. (I am using Berlin in Windows 10)
unit Main;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Grids;
const
WM_MY_MESSAGE = WM_USER + 1;
type
TStringGridEx = class helper for TStringGrid
public
function GetInplaceEditor(): TInplaceEdit;
end;
TForm1 = class(TForm)
aGrid: TStringGrid;
procedure FormCreate(Sender: TObject);
procedure aGridGetEditText(Sender: TObject; ACol, ARow: Integer; var Value: string);
private
procedure OnMyMessage(var Msg: TMessage); message WM_MY_MESSAGE;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.aGridGetEditText(Sender: TObject; ACol, ARow: Integer; var Value: string);
begin
PostMessage(Handle, WM_MY_MESSAGE, 0, 0);
end;
procedure TForm1.FormCreate(Sender: TObject);
var
y: Integer;
x: Integer;
begin
for y := 0 to aGrid.RowCount do
begin
for x := 0 to aGrid.ColCount do // fill the grid
aGrid.Cells[x, y] := Format('Col %d, Row %d'#13#10, [x, y]);
end;
end;
procedure TForm1.OnMyMessage(var Msg: TMessage);
var
pInplaceEdit: TInplaceEdit;
begin
pInplaceEdit := aGrid.GetInplaceEditor();
if Assigned(pInplaceEdit) then
begin
pInplaceEdit.SelStart := pInplaceEdit.EditText.TrimRight.Length;
pInplaceEdit.SelLength := 0;
end;
end;
{ TStringGridEx }
function TStringGridEx.GetInplaceEditor: TInplaceEdit;
begin
Result := InplaceEditor; // get access to InplaceEditor
end;
end.
Sam

Sam
- 2,473
- 3
- 18
- 29
-
-
OK but where do you set SelStart though? Setting it in GetEditText or SetEditText doesn't seem to work. – fullerm Sep 20 '16 at 16:34
-
2@fullerm I am not sure how you are displaying the editor to begin with. If you are using the `ShowEditor` function to start editing, you set the `SelStart` immediately after that. If it is automatic, you have to do more work. Depending on your code and situation. One way is to post a custom message to the main form from inside `OnGetEditText` and later when processing the message you can set the `SelStart`. – Sam Sep 20 '16 at 16:54
-
I am simply clicking the cell to enter edit mode. Setting SelStart in OnGetEditText has no effect. Have you tried it yourself? How would sending an equivalent message be any different? – fullerm Sep 20 '16 at 17:01
-
Sam, for completeness, maybe you could edit your answer to include what you have said here in the comments – Tom Brunberg Sep 21 '16 at 07:22
-
@Sam Have you tried this? I've sent a message from OnGetEditText passing the Col and Row. I then process that message by setting InplaceEditor.SelStart. The cursor doesn't move though. – fullerm Sep 21 '16 at 13:40
-