폼에 트리뷰와 액션리스트 와 이미지리스트를 올려 놓고 이미지 리스트에 적당한 이미지를 읽어 옵니다.
저는
C:\Users\Public\Documents\RAD Studio 9.0 Samples\Delphi\VCL\ActionBands
에 있는 main.pas 에서 이미지 리스트를 복사해옵니다.
ActionList 에 적당하게 액션을 만듭니다.
그리고 액션을 더블 크릭하여 실행문을 만듭니다.
트리뷰에 올릴 액션을 트리뷰를 더블 크릭하여 추가 합니다.
1. 액션을 액션리스트에 읽어와 트리뷰의 노트와 캡션을 비교하여 일치하면 액션을 DATA에 저장합니다.
2. 트리뷰의 OnChange 에서 선택된 액션이 실행 되게 합니다.
3. 액션이 실행 되면 실행된 액션의 캡션과 트리뷰의 노드의 캡션(text)이 일치하는 노드를 선택되게 합니다.
1 단계를 구현하기 위해서 트리뷰에서 캡션으로 찾는 루틴을 이용합니다( 재귀 호출)
이하 소스 갑니다.
unit MainUnit;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ImgList, Vcl.ComCtrls, Vcl.ActnList;
type
TfrmMain = class(TForm)
ActionList1: TActionList;
acOpen: TAction;
acSave: TAction;
acShow: TAction;
acHide: TAction;
acExit: TAction;
TreeView1: TTreeView;
ImageList1: TImageList;
procedure FormCreate(Sender: TObject);
procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
procedure ActionList1Execute(Action: TBasicAction; var Handled: Boolean);
procedure acOpenExecute(Sender: TObject);
procedure acSaveExecute(Sender: TObject);
procedure acShowExecute(Sender: TObject);
procedure acHideExecute(Sender: TObject);
procedure acExitExecute(Sender: TObject);
private
iActiveNode: TTreeNode;
procedure MakeTreeMenu;
function GetTVNodeByCaption(TV: TTreeView; const iCaption: string): TTreeNode;
function GetNodeByCaption(iTreeNode: TTreeNode; iCaption: string): TTreeNode;
public
{ Public declarations }
end;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
procedure TfrmMain.acExitExecute(Sender: TObject);
begin
close;
end;
procedure TfrmMain.acHideExecute(Sender: TObject);
begin
caption:= 'Selected menu is Hide';
end;
procedure TfrmMain.acOpenExecute(Sender: TObject);
begin
caption:= 'Selected menu is Open';
end;
procedure TfrmMain.acSaveExecute(Sender: TObject);
begin
caption:= 'Selected menu is Save';
end;
procedure TfrmMain.acShowExecute(Sender: TObject);
begin
caption:= 'Selected menu is Show';
end;
procedure TfrmMain.ActionList1Execute(Action: TBasicAction; var Handled: Boolean);
var
iTreeNode: TTreeNode;
begin
if Action <> acExit then
if (Action is TAction) then
if (TreeView1.Selected <> nil) and (CompareText(TreeView1.Selected.Text, TAction(Action).Caption)= 0) then begin
iTreeNode:= GetTVNodeByCaption(TreeView1,TAction(Action).Caption);
if (iTreeNode <> nil) and (iTreeNode <> iActiveNode) then
iTreeNode.Selected:= True;
end;
end;
procedure TfrmMain.FormCreate(Sender: TObject);
begin
iActiveNode:= nil;
MakeTreeMenu;
TreeView1.Items.GetFirstNode.Selected:= True;
end;
function TfrmMain.GetNodeByCaption(iTreeNode: TTreeNode; iCaption: string): TTreeNode;
var
jTreeNode: TTreeNode;
begin
Result:= nil;
jTreeNode:= iTreeNode;
while jTreeNode<> nil do begin
if CompareText(jTreeNode.Text, iCaption)=0 then begin
Result:= jTreeNode;
Exit;
end else begin
jTreeNode:= jTreeNode.getFirstChild;
while jTreeNode <> nil do begin
Result:= GetNodeByCaption(jTreeNode, iCaption); // 재귀호출
if Result <> nil then exit;
jTreeNode:= jTreeNode.GetNextChild(jTreeNode);
end;
end;
end;
end;
function TfrmMain.GetTVNodeByCaption(TV: TTreeView; const iCaption: string): TTreeNode;
var
iTreeNode: TTreeNode;
begin
Result:= nil;
iTreeNode:= TV.Items.GetFirstNode;
while iTreeNode <> nil do begin
Result:= GetNodeByCaption(iTreeNode, iCaption); // 자손이 있으면 그 자손에서
if Result <> nil then exit;
iTreeNode:= iTreeNode.getNextSibling; // 다음 node 레벨에 관계없이
end;
end;
procedure TfrmMain.MakeTreeMenu;
var
idx: Integer;
iTreeNode: TTreeNode;
iAction: TAction;
begin
// ActionList 에서 액션을 읽어 옵니다.
for idx := 0 to ActionList1.ActionCount -1 do begin
iAction:= (ActionList1.Actions[idx] as TAction);
if iAction is TAction then begin
iTreeNode:= GetTVNodeByCaption(TreeView1, iAction.Caption);
if iTreeNode <> nil then begin
if not iAction.Visible then
iTreeNode.Delete
else
if iAction.ImageIndex <> -1 then begin
iTreeNode.ImageIndex:= iAction.ImageIndex;
iTreeNode.SelectedIndex:= iAction.ImageIndex;
end;
iTreeNode.Data:= ActionList1.Actions[idx];
end;
end;
end;
end;
procedure TfrmMain.TreeView1Change(Sender: TObject; Node: TTreeNode);
begin
if (Node <> nil) and (Node <> iActiveNode) then
if Assigned(Node.Data) and Assigned(TAction(Node.Data).OnExecute) then
TAction(Node.Data).Execute;
iActiveNode:= Node;
end;
end.
댓글 없음:
댓글 쓰기