TTreeView edit a Node with Enter/Return key lazarus / 31-LCL ---------------------------------------------------------------------- Girlbrush · 2016-11-18 10:46 I'm trying to add keyboard control to a tree view. I have implemented Node movement with CTRL + arrow keys already. When pressing Enter, the Node should go into edit mode (like when double clicking). This works. When pressing Enter again, the edit should be done. It saves the changed Text, but it stays in editing mode until Escape is pressed (in this case, if Enter has been pressed at least once, the changes stick). Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.trvTestKeyUp(Sender: TObject; var Key: Word;  Shift: TShiftState);begin  if curNode = nil then Exit;   case Key of    VK_RETURN:      if not trvTest.IsEditing then        curNode.EditText      else      begin        curNode.EndEdit(false);        trvTest.EditingDone;      end;    VK_ESCAPE:      curNode.EndEdit(true);  end;  //Key:=0;end; I have spent a couple of hours trying to Google a solution, unsuccessfully. If I leave the widget to process the second keypress, I get the same result. EDIT: since I have Form.KeyPreview = true, I have moved the code Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState  );begin  if curNode = nil then Exit;   if ssCtrl in Shift then    case Key of      VK_UP: btnUpClick(Sender);      VK_DOWN: btnDownClick(Sender);      VK_LEFT: btnLinksClick(Sender);      VK_RIGHT: btnRechtsClick(Sender);    end;   case Key of    VK_RETURN:    begin      //Key:=0;      if not trvTest.IsEditing then        curNode.EditText      else      begin        curNode.EndEdit(false);      trvTest.EditingDone;      end;    end;    VK_ESCAPE:      curNode.EndEdit(true);  end;end;                In this scenario, the Node goes into edit mode and immediately exits it.  Lazarus 1.6.2 FPC 3.0.0 Windows 10 Pro x64 ---------------------------------------------------------------------- ASerge · 2016-11-19 20:38 Quote from: Girlbrush on November 18, 2016, 11:46:22 amWhen pressing Enter, the Node should go into edit mode (like when double clicking). This works. When pressing Enter again, the edit should be done. It saves the changed Text, but it stays in editing mode until Escape is pressed (in this case, if Enter has been pressed at least once, the changes stick). This work: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type  THackTreeView = class(TTreeView)    procedure EditorKeyDown(Sender: TObject; var Key : Word; Shift : TShiftState); override;  end; procedure THackTreeView.EditorKeyDown(Sender: TObject; var Key: Word;  Shift: TShiftState);begin  if Key <> VK_RETURN then    inherited;end; { TForm1 } procedure TForm1.FormCreate(Sender: TObject);   procedure ChangeClassForInstance(Instance: TObject; NewClass: TClass);  begin    TClass(Pointer(Instance)^) := NewClass;  end; begin  ChangeClassForInstance(TreeView1, THackTreeView);end; procedure TForm1.TreeView1KeyUp(Sender: TObject; var Key: Word;  Shift: TShiftState);var  CurNode: TTreeNode;begin  if Key = VK_RETURN then  begin    CurNode := TreeView1.Selected;    if (CurNode <> nil) and not TreeView1.IsEditing then      CurNode.EditText;  end;end; ---------------------------------------------------------------------- Girlbrush · 2016-11-21 07:22 Quote from: ASerge on November 19, 2016, 09:38:31 pmQuote from: Girlbrush on November 18, 2016, 11:46:22 amWhen pressing Enter, the Node should go into edit mode (like when double clicking). This works. When pressing Enter again, the edit should be done. It saves the changed Text, but it stays in editing mode until Escape is pressed (in this case, if Enter has been pressed at least once, the changes stick). This work: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type  THackTreeView = class(TTreeView)    procedure EditorKeyDown(Sender: TObject; var Key : Word; Shift : TShiftState); override;  end; procedure THackTreeView.EditorKeyDown(Sender: TObject; var Key: Word;  Shift: TShiftState);begin  if Key <> VK_RETURN then    inherited;end; { TForm1 } procedure TForm1.FormCreate(Sender: TObject);   procedure ChangeClassForInstance(Instance: TObject; NewClass: TClass);  begin    TClass(Pointer(Instance)^) := NewClass;  end; begin  ChangeClassForInstance(TreeView1, THackTreeView);end; procedure TForm1.TreeView1KeyUp(Sender: TObject; var Key: Word;  Shift: TShiftState);var  CurNode: TTreeNode;begin  if Key = VK_RETURN then  begin    CurNode := TreeView1.Selected;    if (CurNode <> nil) and not TreeView1.IsEditing then      CurNode.EditText;  end;end; It did not work. I disabled KeyPreview on the Form and tried, but then CTRL+Down doesn't work (neither does the Enter key as I wanted)... EDIT: seemed to have solved the issue by defining a boolean field to keep track of start of editing: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i // ...private    { private declarations }    curNode : TTreeNode;    justEditing: boolean; // ...procedure TForm1.FormCreate(Sender: TObject);begin  Form1.KeyPreview := false; // Kontrolle mit Tastatur ermöglichen  justEditing := false;   with trvTest do  begin    LoadFromFile(SAVEFILE);    AutoExpand:=true;    DragMode:=dmAutomatic;    ExpandSignColor:=clSkyBlue;    ExpandSignType:=tvestPlusMinus;    HotTrack:=true;  end;// ... procedure TForm1.trvTestKeyDown(Sender: TObject; var Key: Word;  Shift: TShiftState);begin  if Key = VK_RETURN then  begin    justEditing := false;    if trvTest.IsEditing then    begin      curNode.EndEdit(false);      trvTest.EditingDone;    end;  end;   if (ssCtrl in Shift) or (Key = VK_RETURN) then    Key:=0end; procedure TForm1.trvTestKeyUp(Sender: TObject; var Key: Word;  Shift: TShiftState);begin  if not Assigned(curNode) then Exit; // nichts zu tun   if ssCtrl in Shift then    case Key of      VK_UP: btnUpClick(Sender);      VK_DOWN: btnDownClick(Sender);      VK_LEFT: btnLinksClick(Sender);      VK_RIGHT: btnRechtsClick(Sender);    end;   case Key of    VK_ESCAPE:      curNode.EndEdit(true);    VK_DELETE:      menDeleteClick(Sender);    VK_RETURN:    begin      if (not trvTest.IsEditing) and (not justEditing) then      begin        justEditing := true;        curNode.EditText;        trvTest.EditingDone;      end else      begin        //curNode.EndEdit(false);        //trvTest.EditingDone;      end;    end;  end;end;   Right way to handle it? Comments welcome ---------------------------------------------------------------------- Girlbrush · 2016-11-21 12:51 Is a double post Ok if I have another problem now? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.menDeleteClick(Sender: TObject);begin  if Assigned(curNode) then    if MessageDlg('Warnung', 'Sind Sie sicher, dass Sie diesen Eintrag löschen wollen?'#13#10'>>> '    +curNode.Text, mtWarning, [mbYes, mbCancel], 0, mbCancel) = mrYes then      curNode.Delete;end;                   If I use the enter key to dismiss this dialog (the default is Cancel), the treeview thinks I pressed enter in order to edit. I would expect the keypress to be consumed by the MessageDlg! ---------------------------------------------------------------------- ASerge · 2016-11-22 02:26 Quote from: Girlbrush on November 21, 2016, 08:22:09 amIt did not work. Maybe it's not the best solution, but definitely working. I've tested this under Windows and Lazarux 1.6 on an empty project. This is a question about the use Enter for items in the TreeView. About Ctrl+Down was not a question. Perhaps you unsuccessfully copied itself (instead of KeyUp put the code in KeyDown, etc.) or other your code breaks the behavior. ---------------------------------------------------------------------- Girlbrush · 2016-11-22 07:14 Quote from: ASerge on November 22, 2016, 03:26:39 amQuote from: Girlbrush on November 21, 2016, 08:22:09 amIt did not work. Maybe it's not the best solution, but definitely working. I've tested this under Windows and Lazarux 1.6 on an empty project. This is a question about the use Enter for items in the TreeView. About Ctrl+Down was not a question. Perhaps you unsuccessfully copied itself (instead of KeyUp put the code in KeyDown, etc.) or other your code breaks the behavior. Yes it must be some other handling that breaks it. Thank you anyway! ---------------------------------------------------------------------- ASerge · 2016-11-22 16:04 Quote from: Girlbrush on November 21, 2016, 01:51:20 pmIf I use the enter key to dismiss this dialog (the default is Cancel), the treeview thinks I pressed enter in order to edit. I would expect the keypress to be consumed by the MessageDlg!  I found a better solution that avoids and this problem: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type  TOpenTreeView = class(TTreeView);   THackEdit = class(TEdit)  protected    procedure ControlKeyUp(var Key: Word; Shift: TShiftState); override;  end; procedure THackEdit.ControlKeyUp(var Key: Word; Shift: TShiftState);begin  Key := 0;end; { TForm1 } procedure TForm1.TreeView1KeyDown(Sender: TObject; var Key: Word;  Shift: TShiftState);   procedure ChangeClassForInstance(Instance: TObject; NewClass: TClass);  begin    TClass(Pointer(Instance)^) := NewClass;  end; var  CurNode: TTreeNode;begin  if Key = VK_RETURN then  begin    CurNode := TreeView1.Selected;    if CurNode <> nil then    begin      Key := 0;      CurNode.EditText;      ChangeClassForInstance(TOpenTreeView(TreeView1).FEditor, THackEdit);  end;  end;end; ---------------------------------------------------------------------- Girlbrush · 2016-11-23 07:09 Ok, I need to study to understand this one For now, I used another boolean Flag. Thank you