选择更改后如何检索 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 有什么想法吗?
有 OnAddToSelection
和 OnRemoveFromSelection
事件用于跟踪选择的变化,我想你应该使用这些而不是 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
事件处理程序中处理选择 - 无论焦点节点如何变化,选择都可能发生变化。
我有启用了 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 有什么想法吗?
有 OnAddToSelection
和 OnRemoveFromSelection
事件用于跟踪选择的变化,我想你应该使用这些而不是 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
事件处理程序中处理选择 - 无论焦点节点如何变化,选择都可能发生变化。