2

I have a StringGrid which is able to draw new lines using an OnDraw method.

It works fine, but now I want that the user can enter a New Line using the keyboard. At the moment, multiline texts have to be copypasted into the StringGrid.

Everytime VK_RETURN is pressed, the StringGrid leaves the Edit mode. What do I have to do to avoid this?

For the new line, I want to have Ctrl+Return, like it is in Skype.

procedure TForm1.StringGrid1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if (Key = VK_RETURN) and (ssCtrl in Shift) then // Ctrl+Return = New Line
  begin
    // TODO: Do NOT cancel edit mode
    // TODO: Insert #13#10 at current cursor position
  end;
end;
Daniel Marschall
  • 3,739
  • 2
  • 28
  • 67
  • Use the code in [this answer](http://stackoverflow.com/a/20439948/62576), but reverse the logic to move cells down instead of up. – Ken White Jan 08 '16 at 01:34
  • @KenWhite you misunderstood my question. I want to have a multi line text inside the cell, not a new row. – Daniel Marschall Jan 08 '16 at 01:39
  • That's not what you asked. You asked about inserting a new line (which usually indicates row) in the grid. If you want to ask about multi-line text in a stringgrid, ask that question. – Ken White Jan 08 '16 at 02:30
  • @KenWhite: what you linked to is not a duplicate, though. The OP is asking how to let users **edit** a cell's text as multi-line, not how to **display** multi-line text in a cell (the OP already knows how to do that). The question you linked to is all about displaying text, not editing text. And yes, there are ways to allow multi-line editing. What you suggested is one way, but not the only way. – Remy Lebeau Jan 08 '16 at 02:46

1 Answers1

3

TStringGrid's built-in cell editor does not support multi-line text (it is a descendant of TCustomMaskEdit, which is single-line). You will have to use a separate UI control, such as a TMemo, for editing multi-line text. There are a few different ways to accomplish that:

  1. disable the grid's built-in editor (remove the goEditing flag from the grid's Options property) and put a TMemo near the TStringGrid. When the user selects a cell (and optionally clicks a button/menu), assign its current text into the Memo. If the user makes any changes (and optionally clicks another button/menu), assign the new text back to the cell.

  2. a variation of the above: Design a separate TForm that has a TMemo and Save button on it. When the user selects a cell (or pushes a button/menu), assign the cell's current text to the Form's Memo and then show the Form by calling its ShowModal() method. If the user clicks the Save button, close the Form by setting its ModalResult property to mrOk. If ShowModal() returns mrOk, assign the Memo's current text to the cell being edited and then Invalidate() the grid to trigger a repaint. If ShowModal() returns anything else, do nothing.

  3. a variation of the above: leave the grid's built-in editor enabled, and design a separate Form as above, but then configure the TStringGrid to trigger the Form automatically, without having to change the rest of your UI in any way.

    1. derive a new class from TStringGrid and have it override the virtual GetEditStyle() method to return esEllipsis (it returns esSimple by default), and override the virtual CreateEditor() method to return a new instance of a TInplaceEditList-derived class (it returns a TInplaceEdit object by default). This will cause a cell to display a push button instead of an edit field when being edited.

    2. Have your TInplaceEditList-derived class own an instance of your Form, and then override the virtual UpdateContents() method to retrieve the current cell text and assign it to the Form's Memo, and override the virtual DoEditButtonClick() method to show the Form modally and respond to the return value of ShowModal() accordingly.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770