Mega Code Archive

 
Categories / Delphi / VCL
 

Using treeview as a menu

Title: Using treeview as a menu Question: You can use TTreeview as a structured menu in addition to standard menu. It's very easy and requires no coding when you already have a few functions. Answer: { The idea is as follows: You create TActions for every menu item, then assign these actions to menu items. Then you add items to your TreeView component on your main form. TMenu items are associated with TreeView items by comparing their captions, e.g. if you have a menu item with a caption 'Customers' and you have a TreeView item with the same text 'Customers' it is considered that clicking either menu item or TreeView item should invoke the same TAction. You just need to associate proper action with tree view items. Note that you cannot have two menu items having same captions but assigned different actions. } { returns TTreeNode identified by node text ACaption by 'digging' down the tree recursively } function GetNodeByCaption(ACurrNode: TTreeNode; const ACaption: String): TTreeNode; var ANode: TTreeNode; begin Result:=nil; ANode:=ACurrNode; while ANodenil do begin if AnsiSameCaption(ACaption, ANode.Text) then begin Result:=ANode; exit; end else begin ANode := ANode.getFirstChild; while ANodenil do begin Result:=GetNodeByCaption(ANode, ACaption); if Resultnil then Exit else ANode:=ANode.GetNextChild(ANode); end; end; end; end; { returns a TTreeNode which text is ACaption } function GetTVNodeByCaption(tv: TTreeView; const ACaption: String): TTreeNode; var Node: TTreeNode; begin Result:=nil; Node:=tv.Items.GetFirstNode; while Nodenil do begin Result:=GetNodeByCaption(Node, ACaption); if Resultnil then exit; Node:=Node.GetNextSibling;//GetNext doesn't return children?? end; end; { in your main form you need to have a procedure, which associates menu items with tree view nodes: } procedure TfrmZKMain.AssociateTVMenu; var i: Integer; ANode: TTreeNode; begin //aclMenu is the TActionList component where you put all your menu actions for i:=0 to aclMenu.ActionCount-1 do begin if (aclMenu.Actions[i] is TCustomAction) then begin if (aclMenu.Actions[i] as TCustomAction).Caption='-' then Continue; //search for a TTreeNode in the tree view tvMenu which text is equal to the caption of the current TAction ANode:=GetTVNodeByCaption(tvMenu, (aclMenu.Actions[i] as TCustomAction).Caption); if ANodenil then begin //if menu item is invisible, remove treenode with the same caption as invisible menu item if not (aclMenu.Actions[i] as TCustomAction).Visible then begin ANode.Delete; end else begin if (aclMenu.Actions[i] as TCustomAction).ImageIndex-1 then begin //assign the same image to tree node as menu item ANode.ImageIndex:=(aclMenu.Actions[i] as TCustomAction).ImageIndex; ANode.SelectedIndex:=(aclMenu.Actions[i] as TCustomAction).ImageIndex; end; //assign action to tree node, so when it's clicked it will execute an action ANode.Data:=aclMenu.Actions[i]; end; end; end;//if end;//for end; //OnExecute method of the TActionList which holds your menu actions procedure TfrmZKMain.aclMenuExecute(Action: TBasicAction; var Handled: Boolean); var Node: TTreeNode; begin if ActionacExit then //if action is not the one which closes your app, select tree node if (Action is TCustomAction) then if ((tvMenu.Selectednil) and not AnsiSameCaption(tvMenu.Selected.Text, (Action as TCustomAction).Caption)) then begin Node:=GetTVNodeByCaption(tvMenu, (Action as TCustomAction).Caption); if (Nodenil) and (NodeFActiveNode) then begin Node.Selected:=True; end end; end; { write tvMenu OnChange event handler FActive node is a private variable which holds currently selected TreeNode. don't forget to assign FActiveNode:=nil in OnFormCreate event. } procedure TfrmZKMain.tvMenuChange(Sender: TObject; Node: TTreeNode); begin if (Nodenil) and (NodeFActiveNode) then if Assigned(Node.Data) and Assigned(TCustomAction(Node.Data).OnExecute) then TCustomAction(Node.Data).Execute; FActiveNode:=Node; end; //OnFormCreate event handler procedure TfrmZKMain.FormCreate(Sender: TObject); begin FActiveNode:=nil; ....... AssociateTVMenu; //select default tree view item if needed tvMenu.Items.GetFirstNode.Selected:=true; end;