Q&A

  • TActionList에 관하여
지금까지 코딩하면서 사용해 보지 않아서요...
도움말을 봐도 먼소린지도 모리겠구 해서....

죄송합니다만 머하는 건지 설명좀....
2  COMMENTS
  • Profile
    박지용 2005.02.18 22:48


    TAction을 관리해주는 Observer 컴포넌트 입니다...

    TAction은 (Menu On Button etc) OnAction event에 연결되구요...

    아주 유용한 것은 커트롤들의 Caption 및 Enable/disable control이 쉬워집니다.

    TAction.Cation 및 TAction.Enable의 속서을 수정하면

    이 TAction으로 연결된 컨트롤들이 동시에 적용이되는 것죠^^

    그럼 즐 프하세요.
  • Profile
    구창민 2005.02.18 21:07
    안녕하세요..

    예전 박후선 님 강좌를 올려드릴께요..

    보시고 도움 되시길 바랍니다..

    즐거운 프로그래밍 하세요..

                         ◇ VCL - Action과 ActionList ◇

                                                           글 : 박후선(OSOLGIL)
                                                softech(꼴뱅이)ppp.kornet21.net

    ※ 본 강좌는 델파이4의 Help를 기초로 작성되었습니다. 본인이 델파이4를  접한
    지 얼마되지 않아 내용상 오류가 있을 수 있습니다.

    델파이4의 컴퍼넌트 팔레트중 Standard팔레트를 살펴보면 마지막에 처음보는  컴
    퍼넌트 하나가 추가된 것을 볼 수 있다. TActionList라 이름 붙여진 이 컴퍼넌트
    는 윈도우와 메뉴와 버튼을 아이콘으로 가지고 있다. 도대체 무엇을 하는 컴퍼넌
    트 인가?  또 한가지,  Form, Button등  대부분의 VCL  컴퍼넌트의 프로퍼티  중
    Action이라는 프로퍼티가 델파이4에 들어오면서 추가되었다. 이 프로퍼티는 어디
    에 사용되는가? 아쉽게도 Action에 대한 상세한 내용은 델파이 헬프를 통해 찾아
    볼 수 없었다. 헬프상의 개괄적인 내용과 본인이 살펴본 사항들을 함께 묶어 강
    좌를 진행해 보겠다.

    ○ Action의 용도와 개념

    Action의 용도와 개념을 예를 통해 알아보자.

    CloseMenuItem : TMenuItem;
    CloseButton : TSpeedButton;

    위의 예에 폼을 닫는 메뉴아이템인 CloseMenuItem과 역시 폼을 닫는 기능을 하는
    스피드 버튼인 CloseButton이 있다. 이들은 정확히 동일한 기능을 한다. 이 말은
    곧 Caption,  Checked,  Enabled, HelpContext,   Hint, ImageIndex,  ShortCut,
    Visible등의 프로퍼티들이 동일하게 변경되어야  한다는 것을 말한다.  예를들어
    CloseMenuItem이 Disable될 상황이라면 CloseButton 역시 Disable되어야 할 것이
    다. 기존의 델파이 버전에서는 이런 처리를 각각 따로 해주어야 했다. 하지만 이
    것을 TAction을 사용하여 한꺼번에 처리할 수 있다. 아래의 그림을 보자.

    ┌────────────┐       +-------------------------------+
    │Action1 : TAction       ├─┐   | CloseMenuItem : TMenuItem     |
    ├────────────┤  │   | CloseButton : TSpeedButton;   |
    │  Caption               │  │   +-------------------------------+
    │  Checked               │  └──── Action                    |
    │  Enabled               │       |     Caption                   |
    │  HelpContext           │       |     Checked                   |
    │  Hint                  │       |     Enabled                   |
    │  ImgeIndex             │       |     HelpContext               |
    │  ShortCut              │       |     Hint                      |
    │  Visible               │       |     ImageIndex                |
    │                        │       |     ShortCut                  |
    └────────────┘       |     Visible                   |
                                       +-------------------------------+

    위에서 CloseMentItem과 CloseButton의  Action 프로퍼티를 Action1으로  연결한
    다. 여기서 CloseMenuItem, CloseButton과 같이 Action의 영향을 받는  오브젝트
    들을 Action1의 클라이언트라고 부른다.

    이렇게 하면 Action1의 캡션을 바꾸면 그 클라이언트인 CloseMenuItem의 Caption
    과 CloseButton의 Caption이 동시에 바뀐다. 이런식으로 Action1의 프로퍼티만을
    변경하면 그것에 연결된 다른 오브젝트들의 프로퍼티 중 같은 이름의 프로퍼티가
    있다면 Action1과 동일한 값으로 변경된다. 하지만 이것이 Action의 주용도는 아
    니다.

    Action의 주용도는 사용자가 컨트를을 Click했을 때 Action의 OnExecute  이벤트
    핸들러가 호출되는 등 사용자가 어떤 작용을 했을 때 그에 대한 처리를 한꺼번에
    처리할   수  있다는데   있다.  몇몇   VCL   컨트롤들에  Action   프로퍼티와
    ExecuteAction등의 메쏘드가 추가되었는데 이것들이 클라이언트로 작동하게 만드
    는 지원이다.

    이 Action들을 리스트로 관리하는 것이 TActionList 컴퍼넌트다. 위에서  살펴본
    것과 같이 ActionList의 주된 용도는  '사용자 명령들'에 대한 반응을  한곳으로
    집중시키기 위한 것이다. 다시 말해 메뉴나 버튼등 사용자 명령에 반응하는 컨트
    롤들을 통합관리하는 것이다.

    델파이4에서 File-New를  통해  MDI나 SDI   어플리케이션을 생성시키면  그곳에
    ActionList가 자리잡는다. 메뉴와 스피드 버튼간의 관리를 ActionList를 통해 처
    리하고 있다. 컴퍼넌트 팔레트의 Standard 부분에 자리잡을 만큼 앞으로  델파이
    의 기본 컴퍼넌트로서 주요한 역할을 할 것이라 기대된다.

    델파이에는  기본적으로  TAction에서  상속받은  TEditAction,  TWindowAction,
    TDataSetAction등의 Action들이 미리 정의되어 있다. 이것은 코드가 필요없이 사
    용자 반응을 통합 처리하도록 지원된다. 예를들어 Edit 메뉴와 관련된 여러 가지
    Action들이 Edit...라는 이름으로 정의되어  있다. Action List를  더블클릭하면
    나타나는 다이얼로그에서 오른쪽 클릭을 해 컨텍스트 메뉴를 띄운다. 여기서 New
    Standard Action을 선택하면 델파이에서 기본적으로 제공되는 Action들의 리스트
    를 볼 수 있다. 각 Action은 category별로 정리되어 ActionList에 나타난다.  몇
    가지를 추가해 확인해 보기 바란다. 여러분들이 이런 미리 정의된 Action들을 작
    성할 수 있다. 하지만 대부분의 경우 미리 정의된 Action을 사용하지 않고 그대
    로 코딩을 통해 이용한다. {Delphi4}\Demos\RichEdit의  예를 보면 미리 정의된
    Action을 이용하지 않고 개별의 Action을 이용한다.


    ○ ActionList를 통한 Action 제어

    TAction은 앞서 살펴보았듯이 사용자 명령에 대한 응답을 통합관리하기 위해  지
    원된다. Action에 연결되어 관리를 받는 오브젝트들은 Action의  클라이언트라고
    부른다.  이  클라이언트들은   주로 메뉴   아이템이나  버튼종류(TToolButton,
    TSpeedButton, TMenuItem, TButton, TCheckBox, TRadioButton등)이다.

    TActionList는 TAction의 리스트를 관리하는 컴퍼넌트다. 디자인타임에서 Action
    을 다루기 위해서는 이 컴퍼넌트를  이용해야 한다. TActionLink가 Action과  그
    클라이언트간의 연결을 관리한다.

    우선 Standard 컴퍼넌트 팔레트에서 ActionList를 선택 Form이나 DataModule  위
    에 놓아보자. ActionList를 더블클릭하면 Action List Editor가 뜬다. 이것을 통
    해 Action들을 추가하고 삭제, 정렬할 수 있다. 해당 Action의 각 프로퍼티는 오
    브젝트 인스펙터상에 나타난다. Name 프로퍼티는 Action의 구분자가 된다.  나머
    지   프로퍼티와  이벤트(Caption,   Checked,  Enabled,   HelpContext,  Hint,
    ImageIndex, ShortCut, Visible)등은 그 Action과 연결된 컨트롤(이를  클라이언
    트 컨트롤이라 부른다)의 각 프로퍼티에 영향을 준다. 예를들어 클라이언트 컨트
    롤이 메뉴 아이템이라면 위의 프로퍼티 모두의 영향을 받는다. 델파이4에 들어오
    면서 메뉴아이템은 각각의 아이콘을 가질  수 있어 ImageIndex에도 영향을  받는
    다. Win32  팔레트에서 ImageList  컴퍼넌트를 폼에  놓고 그것을  ActionList의
    ImageList 프로퍼티에 지정하면 ImageIndex가 유효하게 된다.

    Form, Button, MenuItem등의 컨트롤들에는  대부분 Action이라는 프로퍼티가  있
    다. ActionList에 Action을 한 개 이상 추가하면 그것이 컨트롤의 Action 프로퍼
    티에 나타나며 드롭다운을 이용해 선택할 수 있다. 이렇게 컨트롤의 Action 프로
    퍼티를 선택하면 그 컨트롤은 ActionList 아이템중 한 Action의 클라이언트 컨트
    롤이 되는 것이다.

    사용 예를들어 보자.  우선 폼에 ActionList를  하나 놓는다. 그위에  TDataSet,
    TDataSource, TDBGrid를 놓고 이들을 하나의 테이블로 연결한다. DBGrid에  테이
    블의 내용이 나타날 것이다. 우선 ActionList1을 더블클릭해 다이얼로그를 연다.
    오른쪽 버튼을 눌러 New Standard Action을 선택하던지 아니면 Ctrl+Insert를 누
    른다. Standard   Action들의 리스트가  나타나는데  이들  중 TDataSetCancel,
    TDataSetEdit, TdataSetFirst,   TDataSetInsert, TDataSetLast,  TDataSetNext,
    TDataSetPost, TDataSetPrior, TDataSetRefresh들을 선택한다. DataSet category
    안에 모두 잡힐  것이다. 이제  폼에 버튼을  여러개 두고  각 버튼의  Action을
    Cancel1, Edit1등의 Action으로 연결하고 어플리케이션을 실행시킨다. 각각의 상
    황에 적절히 변화되는 버튼들을 볼 수 있다. 이것들을 메뉴아이템과도 연결할 수
    있다.

    다른 예를들어보자. 일반적은 TCustomAction을 이용할 경우의 예이다. 이것을 이
    용하면 미리 정의된 처리가 없기 때문에 OnExecute, OnHint, OnUpdate를  이용한
    코드를 Action에 기입해 주어야 한다.

    OnExecute 이벤트 핸들러는 관련 클라이언트 컨트롤에 클릭이 발생했을 때  호출
    된다.

    procedure TForm1.Action1Execute(Sender: TObject);
    begin
      ShowMessage('이곳에 클릭했을 때의 처리를 기입합니다');
    end;

    OnHint 이벤트 핸들러는 클라이언트 컨트롤이 힌트가 필요할 때 처리된다.  이것
    은 Action의 Hint 프로퍼티로도 처리되므로 거의 이용되지 않는다. 하지만, 힌트
    가 경우에 따라 달라지는 등의 경우 이용할 수 있다.

    procedure TForm1.Action1Hint(var HintStr: String; var CanShow: Boolean);
    begin
      HintStr := '이 Action의 클라이언트는 같은 힌트를 가진다';
      CanShow := True;
    end;

    OnUpdate 이벤트 핸들러는 Idle인 상태에서 호출된다. 이것을 통해 주로  컨트롤
    의 Enable이나 Checked등의 설정을 한다.

    procedure TForm1.Action1Update(Sender: TObject);
    begin
      if IsModified then
      begin
        BitBtn1.Enabled := False;
        CheckBox1.Enbeld := False;
      end
      else
      begin
        BitBtn1.Enabled := True;
        CheckBox1.Enabled := True;
      end;
    end;

    [참고] 간혹 ActionList의 다이얼로그에서  New Action을 통해  TCustomAction을
    그대로 이용할 경우, 그 클라이언트들이 모두 Disable되어 있는 것을 보게 된다.
    그 이유는 Action이 처리되지 않으면 그 클라이언트들을 모두 Disable  시켜버리
    기 때문이다. 이 것을 막는 방법은 DisableIfNoHandler 프로퍼티를 False로 바꾸
    어 주면 된다.



    ○ Action Link와 프로퍼티간의 연결
    ActionLink는 Action과 각 VCL 오브젝트들(컴퍼넌트,컨트롤)의 프로퍼티를  연결
    하는 역할을 한다. 사실, ActionLink는 내부적으로 구성되고 사용되기 때문에 개
    발자가 관여할 여지는 없다. Action의 한 프로퍼티를 바꾸면 해당 Action과 연결
    된  모든  클라이언트의  프로퍼티가  바뀐다.  이런  프로퍼티들로는  Caption,
    Checked, Enabled, HelpContext, Hint, ImageIndex, ShortCut, Visible이 있다.

    반대의 경우는 어떠한가? 클라이언트 컨트롤의 프로퍼티에서 Caption,  Checked,
    Enabled, HelpContext, Hint, ImageIndex, ShortCut, Visible 중 하나를  변경하
    면 그것이 Action에 영향을 주는가? 아니다. 그 컨트롤 하나만 변경되고  Action
    이나 그 Action의 클라이언트 컨트롤들에는 영향을 미치지 않는다. 그 자신의 프
    로퍼티만 변경된다.

    [주의] 다시 확인하자. Action의 프로퍼티를  변경하면 그 클라이언트 컨트롤의
    프로퍼티가 바뀌지만 클라이언트 컨트롤에서의 변경은 Action에 영향을 주지  않
    는다.

    ○ Action의 실행

    클라이언트 컴퍼넌트나 컨트롤를 클릭하면 열결된 Action의 OnExecute  이벤트가
    호출된다. 아래의 코드는 Action이 실행될 때 OnExcute 이벤트 핸들러를 통해 클
    라이언트 컨트롤인 툴바의 Visible 프로퍼티를 변경하는 예를 보여준다.

    procedure TForm1.Action1Execute(Sender: TObject);
    begin
      ToolBar1.Visible := not ToolBar1.Visible;
    end;

    참고: 만약 tool button이나 menu  item을 사용하고 있다면 그것을 위한  Images
    프로퍼티를 수동으로  ActionList의  Images 프로퍼티로  연결시켜주어야  한다.
    ImageIndex 프로퍼티가 동적으로 클라이언트에 연결되는 경우에라도 마찬가지다.

    아래는 Cut1이라고 불리는 Action이 실행되는 과정을 보여주고 있다. 여기서  클
    라이언트인   Speedbutton1은  자신의   Action  프로퍼티로   Cut1에  연결되고
    Speedbutton1의 Click 메쏘드는 Cut1의 Execute 메쏘드를 호출하게 된다.

    1. SpeedButton1의 클릭이 Cut1.Execute이 호출되게 한다.
    2. Cut1은 우선 자신의 ActionList인 ActionList1에게 실행될 기회를  주기위해.
       ActionList1.ExecuteAction을 호출한다. 이때 Cut1 자신을 인자로 준다.
    3. ActionList1은 ExecuteAction을 위해 자신의 이벤트 핸들러인 OnExecute을 호
       출한다. ExecuteAction은   ActionList에 있는  모든  action들에  적용된다.
       OnExecute 핸들러는 Handled라는 인자를 가지고 있는데 디폴트로 False가  되
       돌려진다. 만약에 핸들러가 할당되었고  이벤트를 처리했다면 True를  돌려야
       한다. True가 되면 일련의 작업이  거기서 끝나게 된다. 예를들면 아래와  같
       다.

       procedure TForm1.ActionList1ExecuteAction(Action: TBasicAction;
         var Handled: Boolean);
       begin
         { 다른 남은 Action들을 더 이상 처리하게 하지 않기 위해 True를 설정 }
         Handled := True;
       end;

       만약 위의   시점에서 실행이  처리되지 않았다면   나머지 Action들을  위해
       Handled를 False로  주던지 아무런  값을  설정하지 않으면  된다. 기본값이
       False이므로 값을 지정하지 않아도 무방하다. 이렇게 하면 ActionList의 다른
       Action들을 위해 일련의 작업은 계속된다.

    4. Cut1 action은 Application 오브젝트의 ExecuteAction 메쏘드에  라우트된다.
       이 메쏘드는 OnActionExecute 이벤트 핸들러를 호출한다.  ExectueAction 메
       쏘드는 어플리케이션에 있는 모든 Action List들에게 처리를 전달한다.  처리
       방법은 Action List의 ExecuteAction과 동일하다. OnActionExecute  핸들러가
       작성되어 있고 그것이 이벤트를 처리하였다면 Handled 인자에 True를  설정하
       여야 한다. 이렇게 하면 일련의 작업들은 여기서 끝난다. 예를들면 아래와 같
       다.

       procedure TForm1.ApplicationExecuteAction(Action: TBasicAction;
         var Handled: Boolean);
       begin
         { 다른 Application안의 ActionList에게 이벤트를 전달하는 것을 막음  }
         Handled := True;
       end;

       만약의 실행이  Application 이벤트  핸들러에서 처리되지  않았다면  Cut1은
       CM_ACTIONEXECUTE 메지시를 그 자신을 인자로 하여 어플리케이션의 WndProc로
       보낸다. 그렇게 하면 Application은 해당 Action을 실행시킬 타겟을 찾는다.

    ○ Action의 업데이트

    Application이 idle상태일 때, 비주얼  컨트롤이나 화면에 나타난  메뉴아이템과
    연결된 모든  Aciton의  OnUpdate 이벤트가   발생한다. 이것은  어플리케이션이
    enable이나 disable등의 작업을 중앙에서 한코드로 처리할 수 있는 기회를  부여
    한다. 예를들어 아래의 코드는 Toolbar가 Visible일 때 Action의 Checked를 True
    로 만드는 OnUpdate핸들러의 예다.

    procedure TForm1.Action1Update(Sender: TObject);
    begin
      { 툴바가 현재 Visible인가 아닌가를 나타냄 }
      (Sender as TAction).Checked := ToolBar1.Visible;
    end;

    {Delphi4}\Demos\RichEdit의 내용을 살펴보면 Action의 사용에 대해 배울 수  있
    다.

    ○ Action과 관련된 소스코드

    기본적인  Action들이   StdActns, DBActns   유닛에  포함되어   있다.  이들을
    Predefined Action이라고   부른다. Pre-defined  Action은  크게  TEditAction,
    TWindowAction, TDataSetAction의 세그룹으로 나눈다. Action 컴퍼넌트를 작성하
    기 위해 이것들을 살펴보는 것이 좋다.

    StdActns.pas
      TEditAction(TEditCut, TEditCopy, TEditPaste)
      TWindowAction(TWindowClose, TWindowCascade, TwindowTileHorizontal,
        TWindowTileVertical, TWindowMinimizeAll, TWindowArrange)

    StdActns에는 Edit메뉴와 관련된 Cut, Copy, Paste등을 처리하기 위한  Action과
    Window   메뉴와  관련된   Close,  Cascade,   TileHorizontal,  TileVertical,
    MinimizeAll,   Arrage등을   처리하는   Action들이   들어   있다.   이것들은
    New-Projects-SDI Application, New-Projects-MDI  Application를 이용해  SDI나
    MDI 어플리케이션을 생성해 보면 그 사용법을 자세히 알 수 있다.

    한편, DataSet과 관련된 Action은 DBActns.pas안에서 찾아볼 수 있다.

    DBActns.pas
      TDataSetAction( TDataSetFirst, TDataSetPrior, TDataSetNext, TDataSetLast,
        TDataSetInsert, TDataSetDelete, TDataSetEdit, TDataSetPost,
        TDataSetCancel, TDataSetRefresh )

    DBActns.pas에서는 First,  Prior, Next,  Last, Insert,  Delete, Edit,  Post,
    Cancel, Refresh등의 DataSet의 조작과 관련된 Action들이 자리잡고 있다.


    컴퍼넌트를 작성할 때 StdActns와 DBActns  유닛을 예로 참고하면 좋다.  이들은
    Action과 연결된 control이나 컴퍼넌트들이 어떻게 동작할 것인가를 설정하는 좋
    은  예들이다.  TEditAction과  TWindowAction들은  일반적으로  HandlesTarget,
    UpdateTarget 메쏘드를 오버라이드하며 나머지  메쏘드들을 이용해 타겟을  특정
    클래스나 오브젝트로 제한한다. 각  Action별 동작을 위해서는  ExecuteTarget을
    통해 그 동작을 설정한다.


    그 외 Aciton과 관련된 소스코드는 아래의 위치에서 찾아 볼 수 있다.

    ActnList.pas:
      TAction, TActionLink, TActionList, TContainedAction, TCustomAction,
      TCustomActionList
    Classes.pas:
      TBasicAction, TBasicActionLink
    Controls.pas:
      TControlActionLink, TWinControlActionLink
    ComCtrls.pas:
      TToolButtonActionLink
    Menus.pas:
      TMenuActionLink
    StdCtrls.pas:
      TButtonActionLink


    ○ Action Component의 예

    TAction은  ActionList를   더블클릭하여  추가할   수  있다.   위에서  살펴본
    TEditAction과 TWindowAction, TDataSetAction등의 기본 Action도 추가할 수  있
    다.

    TEditAction만 살펴보자. 모든 Edit관련 Action들을 위한 베이스 클래스고, 이를
    상속받은 Copy, Cut, Paste들은 윈도우 클립보드 조작과 관련된 클래스다.

            TEditCopy 선택된 텍스트를 클립보드에 복사한다.
            TEditCut 타겟으로부터 텍스트를 잘라내어 클립보드에 넣는다.
            TEditPaste 클립보드로부터 텍스트를 타겟에 잘라넣는다.

    이들의 실제 소스코드를 보면 아주 간단하다는 것을 알 수 있다. 소스코드를 열
    어 TEditAction 부분을 살펴보자. 강좌란에서 500라인 넘게 올릴 수 없고 한 강
    좌에 이 내용을 마치고 싶은 생각에 소스코드는 이곳에 기입하지 않았다.

    GetControl은 Target을 TCustomEdit로 Typecast한다. ExecuteTarget 메쏘드를 오
    버라이드하여 사용자가 클릭하였을 때 어떻게 동작할 것인가를 지정한다. 이렇게
    많이 사용되는 Action은 상속받은 클래스로 처리하지만 일반적인 다른  Action들
    은 해당 Action의 OnClick을 이용해 처리하는 것이 일반적이다.

    ○ Action이 타겟을 찾는 법

    1. 우선 CM_ACTIONEXECUTE 메시지가 어플리케이션에 주어지면 먼저 그것을  화면
       상의 활성폼(Active Form)으로 보낸다. 만약에 화면상의 활성폼이 없다면  어
       플리케이션은 그것을 메인폼으로 보낸다. 이 메시지에는 Action이 인자로  들
       어있다. 이 Action을 Cut1이라고 하자.

    2. 메시지를 받은 폼이 Form1이라고 가정하자. Form1은 현재 활성 컨트롤을 찾아
       컨트롤의 ExecuteAction 메쏘드를 호출한다. 이  때 인자로는 Cut1이 주어진
       다.

    3. 활성 컨트롤이 Memo1이라고 가정하자. Memo1은 Cut1의 HandlesTarget  메쏘드
       를 호출한다. 이 때 인자로  Memo1 자신을 주어서 자신이 적당한  타겟인지를
       Cut1이  확인할  수  있게  한다.  만약  Memo1이  적절한  타겟이  아니라면
       HandlesTarget은 False를 되돌리며 Memo1의 ExecuteAction 역시 False를 되돌
       린다.

    4. 만약 Memo1이 Cut1을 위한 적당한 타겟이라면, HandelsTarget은 True를  되돌
       린다. 이 때, Memo1은 Cut1.ExecuteTarget을  호출하고 인자로 자신을 준다.
       마지막으로 Memo1의 선택부분을 Cut1.ExecuteTarget은 클립보드로 잘라  넣는
       다.

       procedure TEditCut.ExecuteTarget(Target: TObject);

       begin
         GetControl(Target).CutToClipboard;
       end;

    5. 만약 컨트롤이 적당한 타겟이 아니면 일련의 작업이 계속된다. Form1은  자신
       의 ExecuteAction   메쏘드를 호출한다.  만약  Form1이  적당한 타겟이라면
       Cut1.ExecuteTaget 메쏘드를 호출하고 자신을  인자로 넘긴다. 만약  Form1이
       적당한 타겟이 아니라면 Form1은 타겟을 찾을 때 까지 자신이 포함하고  있는
       모든 Visible 컨트롤들의 ExecuteAction을 호출한다.

    [참고] 간혹 ActionList의 다이얼로그에서  New Action을 통해  TCustomAction을
    그대로 이용할 경우, 그 클라이언트들이 모두 Disable되어 있는 것을 보게 된다.
    그 이유는 Action이 처리되지 않으면 그 클라이언트들을 모두 Disable  시켜버리
    기 때문이다. 이 것을 막는 방법은 DisableIfNoHandler 프로퍼티를 False로 바꾸
    어 주면 된다.

    ○ Action을 등록시키는 법

    자신이 작성한 Action 컴퍼넌트들을 IDE에 등록시키거나 등록해제하기  위해서는
    ActnList 유닛에 있는 아래 두 개의 프로시져를 이용한다.


    procedure RegisterActions(const CategoryName: string; const AClasses: array
    of TBasicActionClass);
    procedure UnRegisterActions(const AClasses: array of TBasicActionClass);

    이 때 category로 Action들을 그룹화 시킬 수 있다.

    { 표준Action의 등록예 }
    RegisterActions('', [TAction]);
    RegisterActions('Edit', [TEditCut, TEditCopy, TEditPaste]);
    RegisterActions('Window', [TWindowClose, TWindowCascade,
      TWindowTileHorizontal, TWindowTileVertical, TWindowMinimizeAll,
      TWindowArrange]);

    ○ ActionList 에디터의 작성

    ActionList를 위한 자신의 컴퍼넌트 에디터를 작성하고 싶은 경우, ActnList  유
    닛에 포함된 아래의 네가지 전역 프로시져 변수를 이용할 수 있다.

    CreateActionProc: function (AOwner: TComponent; ActionClass:
      TBasicActionClass): TBasicAction = nil;
    EnumRegisteredActionsProc: procedure(Proc: TEnumActionProc; Info: Pointer)
      = nil;
    RegisterActionsProc:procedure (const CategoryName: string; const AClasses:
      array of TBasicActionClass; Resource: TComponentClass) = nil;
    UnRegisterActionsProc: procedure (const AClasses: array of
      TBasicActionClass) = nil;

    Action들의 등록과 등록헤제, 생성, enumeration등을 처리하기 위해 여러분 자신
    의 핸들러를 작성하고 initialization 부분에 위의 프로시져 변수들에 그것을 할
    당시키면 된다.