2012년 10월 16일 화요일

TreeView Menu

트리뷰로 메뉴를 구현 해보겠습니다.

폼에 트리뷰와 액션리스트 와 이미지리스트를 올려 놓고 이미지 리스트에 적당한 이미지를 읽어 옵니다.
저는
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.



댓글 없음:

델파이 12.1이냐 11.3이냐?

 델파이가 12.1이 나왔습니다. 혹시 11.3버전의 커뮤니티버전이 필요하시는분이 있을 수 있을 것 같아 https://altd.embarcadero.com/.../RADStudio_11_3_esd_28... 와 이것 찾느랴 엄청고생함.