Del键在动态重新定义快捷键时会删除整个treeview。

3

我有以下代码:

procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
var
  m: TMenuItem;
begin
  // Here, some dynamic stuff is done, so every node gets individual items in the mainmenu
  Node1.Clear;

  m := TMenuItem.Create(Self);
  m.Caption := 'Delete';
  m.ShortCut := VK_DELETE;
  m.OnClick := AcDelete;
  Node1.Add(m);
end;

procedure TForm1.AcDelete(Sender: TObject);
begin
  if not Assigned(TreeView1.Selected) then Exit;
  TreeView1.Selected.Delete;
end;

procedure TForm1.TreeView1Deletion(Sender: TObject; Node: TTreeNode);
begin
  // Only when I do this, the "Del"-key-loop will break. But then, the new
  // selected item won't get new menu individual items.
  // TreeView1.OnChange := nil;
end;

在表单上有一个 TMainMenu 和一个TTreeView。每当在树视图中选择某个节点,都会为每个节点创建一个单独的菜单。该菜单通常包括“删除节点”,其快捷键为 [Del]。但是,这也必须动态创建。
当我按下 [Del] 键时,该项将被 AcDelete 删除,并且当然会选择后续节点。由于选择了后续节点,TreeView1Change 就会调用,从而创建新的单独菜单。到目前为止一切顺利。
问题是,VCL 仍然认为 [DEL] 键被按下,因此后续节点也会被删除。接着它的后继节点也会被删除,依此类推,直到整个列表为空。当然,如果我使用鼠标,就不会发生这种情况。
我应该怎么做才能告诉 VCL 在创建新菜单时,[Del] 键已经没有被按下了呢?我可以在 TreeView1Deletion 中做些解决方法吗?
DFM 代码:
object Form1: TForm1
  Left = 192
  Top = 107
  Width = 1305
  Height = 750
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  Menu = MainMenu1
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object TreeView1: TTreeView
    Left = 128
    Top = 56
    Width = 233
    Height = 193
    Indent = 19
    TabOrder = 0
    OnChange = TreeView1Change
    OnDeletion = TreeView1Deletion
    Items.Data = {
      04000000220000000000000000000000FFFFFFFFFFFFFFFF0000000000000000
      09323334323334323334210000000000000000000000FFFFFFFFFFFFFFFF0000
      0000000000000832336173647361641F0000000000000000000000FFFFFFFFFF
      FFFFFF0000000000000000067274656574721E0000000000000000000000FFFF
      FFFFFFFFFFFF0000000000000000053333333333}
  end
  object MainMenu1: TMainMenu
    Left = 88
    Top = 80
    object Node1: TMenuItem
      Caption = 'Node'
    end
  end
end

可能出现这种行为是因为在快捷方式处理完成之前,您正在创建具有相同快捷方式的新项目。按照TLama的建议去做,它应该解决问题,并且更加干净。 - Andrei Galatyn
我知道如何操作。但是我需要节点类定义所有可以执行的操作。由于代码将由不同的节点类型扩展,我不想在表单中硬编码所有内容。 - Daniel Marschall
@rinntech,抱歉,我没有理解你的意思。你要做的就是在树的OnChange事件中设置DeleteNodesAction.Visible := YourConditionToAllowDeletion;,然后如果将该操作绑定到更多控件,则所有控件都会消失。你目前总是添加该菜单项,这总是保持快捷方式处于活动状态。你必须仅在节点可以删除时添加它,或者我没有理解这个问题的重点吗? - TLama
@David,Node1是一个父菜单项,新创建的菜单子项m将被添加到其中。 - TLama
哦,我明白了。那个信息在 .dfm 文件中。 - David Heffernan
显示剩余7条评论
1个回答

1
添加1个动作DeleteAction:TAction,并分配了快捷键(DEL)。更改代码如下:
procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
var
  m: TMenuItem;
begin
  // Here, some dynamic stuff is done, so every node gets individual items in the mainmenu
  Node1.Clear;

  m := TMenuItem.Create(Self);
  m.Caption := 'Delete';
  m.Action := DeleteAction;
  DeleteAction.OnExecute := AcDelete;
  Node1.Add(m);
end;

procedure TForm1.AcDelete(Sender: TObject);
begin
  if not Assigned(TreeView1.Selected) then Exit;
  TreeView1.Selected.Delete;
end;

procedure TForm1.TreeView1Deletion(Sender: TObject; Node: TTreeNode);
begin
  // Only when I do this, the "Del"-key-loop will break. But then, the new
  // selected item won't get new menu individual items.
  // TreeView1.OnChange := nil;
end;

它应该会有所帮助(因为我们不再在运行时创建具有相同快捷方式的项目)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接