3

I am learning TVirtualStringTree usage and must implement an incremental search. When the user enters characters into a TEdit I want to move the focused node to the first qualifying node in the tree.

I'm reading through all the demo and example code I can find and cannot seem to find a starting place for this. Can anyone get me started with pseudo code or better?

Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
greymont
  • 39
  • 1
  • 3

2 Answers2

6

The control supports incremental searching already. You don't need to add any edit control; just start typing into the tree control, and it will select the next matching node. Set the IncrementalSearch, IncrementalSearchDirection, IncrementalSearchStart, and IncrementalSearchTimeout properties as needed.

To select the first node that matches given criteria, use IterateSubtree. Write a method matching the signature of TVTGetNodeProc to check a single node against your search criteria. It will be called for each node in the tree, and if the node matches, then it should set the Abort parameter to true. Use the third parameter of IterateSubtree (named Data) to communicate the search term to your callback function along with any other search criteria.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
4

I've stripped some of the unnecessary code, but here you go:

unit fMyForm;

interface

uses
  Windows, Messages, Forms, StdCtrls, VirtualTrees, StrUtils;

type
  TfrmMyForm = class(TForm)
    vstMyTree: TVirtualstringTree;
    myEdit: TEdit;
    procedure myEditChange(Sender: TObject);
  private
    procedure SearchForText(Sender: TBaseVirtualTree; Node: PVirtualNode; Data: Pointer; var Abort: Boolean);
  end;

  PDatastructure = ^TDatastructure;
  TDatastructure = record
    YourFieldHere : Widestring;
  end;

implementation

{$R *.dfm}

procedure TfrmMyForm.SearchForText(Sender: TBaseVirtualTree; Node: PVirtualNode; Data: Pointer; var Abort: Boolean);
var
  NodeData: PDatastructure; //replace by your record structure
begin
  NodeData := Sender.GetNodeData(Node);
  Abort := AnsiStartsStr(string(data), NodeData.YourFieldHere); //abort the search if a node with the text is found.
end;

procedure TfrmMyForm.myEditChange(Sender: TObject);
var
  foundNode : PVirtualNode;
begin
  inherited;
  //first param is your starting point. nil starts at top of tree. if you want to implement findnext
  //functionality you will need to supply the previous found node to continue from that point.
  //be sure to set the IncrementalSearchTimeout to allow users to type a few characters before starting a search.
  foundNode := vstMyTree.IterateSubtree(nil, SearchForText, pointer(myEdit.text));

  if Assigned (foundNode) then
  begin
    vstMyTree.FocusedNode := foundNode;
    vstMyTree.Selected[foundNode] := True;
  end;
end;

end.
TedOnTheNet
  • 1,082
  • 1
  • 8
  • 23