TeeTree provides a rich event system for responding to mouse clicks, keyboard input, and other user interactions. Events are available at both the tree level and individual node/connection level.
Events are defined in TeeTree.pas starting at line 1848. Both VCL and FMX versions share the same event signatures.
From TeeTree.pas line 2215-2216: property OnClickConnection: TClickConnectionEvent
Fired when clicking empty tree area:
procedure TForm1.Tree1ClickBackground( Sender: TCustomTree; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);begin // Clear selection when clicking background Tree1.Selected.Clear; // Or add new node at click position if Button = mbLeft then with Tree1.Add('New Node') do begin X0 := X; Y0 := Y; end;end;
From TeeTree.pas line 2214: property OnClickBackground: TTreeClick
procedure TForm1.Tree1MouseMove( Sender: TObject; Shift: TShiftState; X, Y: Integer);var Node: TTreeNodeShape;begin // Find shape under mouse Node := Tree1.ClickedShape(X, Y); if Assigned(Node) then begin // Show hint or highlight StatusBar1.SimpleText := Node.Text.Text; Node.Border.Color := clHighlight; end else StatusBar1.SimpleText := '';end;
From TeeTree.pas (lines 7990-7995):
// Call the OnMouseMove event if assignedprocedure TTreeNodeShape.DoMouseMove(...);begin if Assigned(FOnMouseMove) then FOnMouseMove(Self, Shift, X, Y);end;
procedure TForm1.Tree1KeyDown( Sender: TObject; var Key: Word; Shift: TShiftState);begin case Key of VK_DELETE: begin // Delete selected nodes if MessageDlg('Delete selected nodes?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then Tree1.Selected.Delete; Key := 0; // Mark as handled end; VK_ESCAPE: begin // Clear selection Tree1.Selected.Clear; Key := 0; end; VK_F2: begin // Edit selected node if Tree1.Selected.Count > 0 then Tree1.Selected.First.Edit; Key := 0; end; VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT: begin // Navigation handled automatically // But you can customize behavior here end; end; // Check modifier keys if ssCtrl in Shift then begin case Key of Ord('C'): Tree1.Selected.Copy; // Ctrl+C Ord('V'): Tree1.Selected.Paste; // Ctrl+V Ord('X'): Tree1.Selected.Cut; // Ctrl+X Ord('A'): SelectAllNodes; // Ctrl+A end; end;end;
procedure TForm1.Tree1StartEditing( Sender: TTreeNodeShape);begin // Save original text for potential cancel FOldText := Sender.Text.Text; // Or prevent editing certain nodes if Sender.Tag = 1 then begin ShowMessage('This node cannot be edited'); Sender.StopEditing; end;end;
2
OnStopEditing
Fired when editing completes:
procedure TForm1.Tree1StopEditing( Sender: TTreeNodeShape);begin // Validate new text if Trim(Sender.Text.Text) = '' then begin ShowMessage('Text cannot be empty'); Sender.Text.Text := 'Unnamed'; end; // Update database, etc. SaveNodeToDatabase(Sender);end;
From TreeEd.pas (line 4207), the editor uses this:
procedure TForm1.Tree1ExpandingCollapsing( Sender: TTreeNodeShape; var Expand: Boolean);begin if Expand then begin // Before expanding if Sender.Children.Count = 0 then begin // Load children on-demand (virtual mode) LoadChildrenFromDatabase(Sender); end; // Or prevent expansion if not UserHasPermission(Sender) then begin ShowMessage('Access denied'); Expand := False; // Cancel expansion Exit; end; end else begin // Before collapsing // You can prevent collapse by setting Expand := True if Sender.Tag = 1 then // Keep important nodes expanded Expand := True; end;end;
From TeeTree.pas (lines 12654-12657):
if Assigned(FOnExpandingCollapsing) then FOnExpandingCollapsing(AShape, Value);AShape.FExpanded := Value; // After calling event
The Expand parameter is var - you can modify it to cancel the expand/collapse action.
procedure TForm1.Tree1MovingShape( Sender: TTreeNodeShape; var DeltaX, DeltaY: Integer);begin // Snap to grid while dragging DeltaX := (DeltaX div 10) * 10; DeltaY := (DeltaY div 10) * 10; // Or constrain movement if Sender.X0 + DeltaX < 0 then DeltaX := -Sender.X0; // Don't move past left edgeend;
procedure TForm1.Tree1ResizingShape( Sender: TTreeNodeShape; ACorner: TTreeShapeHandle; var DeltaX, DeltaY: Integer);begin // Maintain aspect ratio if ssShift in GetKeyState then begin if Abs(DeltaX) > Abs(DeltaY) then DeltaY := DeltaX else DeltaX := DeltaY; end; // Enforce minimum size if (Sender.Width + DeltaX < 50) then DeltaX := 50 - Sender.Width;end;