Fast scrolling in Delphi Virtual Treeview

[This is an updated version of a question posted earlier, the previous name was selecting node by index in Delphis Virtual Treeview.]

After most of the day, I believe that I have a Virtual Treeview component (powerful but sophisticated) that works in a simple form with two tables.

Now I'm trying to just select 1,512 (for example) top-level nodes. I see no way to do this otherwise than get the first top level node and then call GetNextSibling 1,511 in a loop.

It seems useless. Is there an easier way?

UPDATE

Since initialization of nodes in my tree requires access to the database, initialization of all nodes at startup is not possible. When a user starts with a form without a record already selected, thatโ€™s fine. When the user scrolls the tree, there are enough nodes to display the current window in the tree, and the performance is fine.

When the user starts the form in dialog mode with the database record already selected, I must advance the tree to this node before the user sees the form. This is a problem because if the record goes to the end of the tree, it may take ten seconds when I walk through the tree from the first node. Each time I can GetNextSibling (), the node is initialized, although the vast majority of these nodes are not displayed to the user. I would prefer to delay the initialization of these nodes to the point at which they become visible to the user.

I know that there must be a better way, because if I open the tree without the selected record and use the vertical scroll bar to move in one operation to the middle of the tree, then the correct nodes are displayed without to initialize the nodes that I skipped.

, , . node, , , , , ( ).

, , , , , . "/" , , .

+3
3

node , NextSibling (. TVirtualNode).

+3

, , . 1512- - . , , . , :

function GetNthNextSibling(Node: PVirtualNode; N: Cardinal;
  Tree: TBaseVirtualTree = nil): PVirtualNode;
begin
  if not Assigned(Tree) then
    Tree := TreeFromNode(Node);
  Result := Node;
  while Assigned(Result) and (N > 0) do begin
    Dec(N);
    Result := Tree.GetNextSibling(Result);
  end;
end;

, . , PVirtualNode , 1512- . , .

, . ? PVirtualNode, ( , , , , node, )?

+3

:

, , , , , .

, Y, 0. , , node . , , , .

Y node, node,

function TBaseVirtualTree.GetNodeAt(X, Y: Integer; Relative: Boolean;
  var NodeTop: Integer): PVirtualNode;

The y-node coordinate is the sum of the heights of all previous visible nodes. Assuming you don't have collapsed nodes (so it's either a flat list of records, or all nodes with child nodes expand), and they all have a default height, it's easy. This code should be a good starting point:

procedure TForm1.SelectTreeNode(AIndex: integer; ACenterNodeInTree: boolean);
var
  Y, Dummy: integer;
  Node: PVirtualNode;
begin
  Y := Round((AIndex + 0.5) * VirtualStringTree1.DefaultNodeHeight);
  Node := VirtualStringTree1.GetNodeAt(0, Y, False, Dummy);
  if Node <> nil then begin
    Assert(Node.Index = AIndex);
    VirtualStringTree1.ScrollIntoView(Node, ACenterNodeInTree);
    VirtualStringTree1.Selected[Node] := True;
    VirtualStringTree1.FocusedNode := Node;
  end;
end;
0
source

Source: https://habr.com/ru/post/1731714/


All Articles