选择更改后如何检索 VirtualStringTree 中的选定节点?

How to retrieve selected nodes in VirtualStringTree after selection changed?

我有启用了 MultiSelect 选项的 VST。当 selection 通过键盘事件发生变化时,如何在 VirtualStringTree 中检索 selected 节点列表?

我尝试在 OnFocusChanged 事件中使用以下代码

procedure TForm1.UpdateSelection(VST: TVirtualStringTree);
Var
  NodeArray: TNodeArray;
  NodeData: PNodeData;
  I: Integer;
begin
  Memo1.Clear;

  NodeArray := VST.GetSortedSelection(False);
  For I := Low(NodeArray) to High(NodeArray) do
  Begin
    NodeData := VST.GetNodeData(NodeArray[I]);
    Memo1.Lines.Add(NodeData.Caption);
  End;
end;

procedure TForm1.VST1FocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
    Column: TColumnIndex);
begin
  UpdateSelection(VST1);
end;

如果我使用鼠标和 shift 键,这很好用,但是,如果我使用键盘,即 select 节点,然后按 shift 然后向下箭头到 select 多个节点, selection returns 完整列表 - 1.

这似乎是一个错误?关于如何在使用键盘时获得完整的 selection 有什么想法吗?

OnAddToSelectionOnRemoveFromSelection 事件用于跟踪选择的变化,我想你应该使用这些而不是 OnFocusChanged 事件。

做了一个快速测试,似乎当 OnAddToSelection 触发 GetSortedSelection 方法时 returns 已经选择的节点数组和要选择的节点(或添加到选择中) 作为 Node 参数。

OnRemoveFromSelection 触发GetSortedSelection 方法时returns 所选节点的数组和Node 参数是要从选择中删除的节点。所以你可以说这些事件并不完全 "symmetrical".

当在 OnRemoveFromSelection 中使用 GetSortedSelection 方法时,应用程序确实会在退出时执行 AV。我会说这是 VT 中的一个错误。在表单的 OnDestroy 处理程序中设置 VT.OnRemoveFromSelection := nil; 似乎可以解决问题...因为您似乎有自己的解决方案,所以我没有进一步调查。

我也可以重现此行为(D5,VT 版本 4.5.5)。在我看来像是一个错误,我会解释原因:

似乎键盘事件调用了 FocusChanged,但在触发 FocusChanged 事件时并未更改内部 FSelectedCount。如果您查看 GetSortedSelection 的代码,第一行是 SetLength(Result, FSelectionCount); 并且如果您测试 VST1.SelectionCount 属性 它被设置为实际选择计数 - 1(如您所描述的) 或者如果您按 SHIFT-END,先前的 值将保留。

我从来没有在我自己的应用程序中注意到这一点,因为我在这个特定事件中通过 PostMessage 使用了延迟操作。当事件处理程序退出时,这会产生正确的内部结构。这可能是一个解决方案。

但是,我认为正确的解决方案是在 OnChange 事件处理程序中处理选择 - 无论焦点节点如何变化,选择都可能发生变化。