1

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.

fullerm
  • 406
  • 1
  • 8
  • 23
  • 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 Answers2

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
  • How? TStringGrid has nothing like SelStart that I can see. – fullerm Sep 20 '16 at 16:09
  • 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
  • @fullerm I just added the example that I have tested to my answer. – Sam Sep 21 '16 at 14:30