Delphi Programming Guide
Delphi Programmer 

Menu  Table of contents

Part I - Foundations
  Chapter 1 – Delphi 7 and Its IDE
  Chapter 2 – The Delphi Programming Language
  Chapter 3 – The Run-Time Library
  Chapter 4 – Core Library classes
  Chapter 5 – Visual Controls
  Chapter 6 – Building the User Interface
  Chapter 7 – Working with Forms
Part II - Delphi Object-Oriented Architectures
  Chapter 8 – The Architecture of Delphi Applications
  Chapter 9 – Writing Delphi Components
  Chapter 10 – Libraries and Packages
  Chapter 11 – Modeling and OOP Programming (with ModelMaker)
  Chapter 12 – From COM to COM+
Part III - Delphi Database-Oriented Architectures
  Chapter 13 – Delphi's Database Architecture
  Chapter 14 – Client/Server with dbExpress
  Chapter 15 – Working with ADO
  Chapter 16 – Multitier DataSnap Applications
  Chapter 17 – Writing Database Components
  Chapter 18 – Reporting with Rave
Part IV - Delphi, the Internet, and a .NET Preview
  Chapter 19 – Internet Programming: Sockets and Indy
  Chapter 20 – Web Programming with WebBroker and WebSnap
  Chapter 21 – Web Programming with IntraWeb
  Chapter 22 – Using XML Technologies
  Chapter 23 – Web Services and SOAP
  Chapter 24 – The Microsoft .NET Architecture from the Delphi Perspective
  Chapter 25 – Delphi for .NET Preview: The Language and the RTL
  Appendix A – Extra Delphi Tools by the Author
  Appendix B – Extra Delphi Tools from Other Sources
  Appendix C – Free Companion Books on Delphi
  List of Figures    
  List of tables    
  List of Listings    
  List of Sidebars  

Previous Section Next Section

Defining Custom Actions

In addition to defining custom components, you can define and register new standard actions, which will be made available in the Action List component's Action Editor. Creating new actions is not complex. You have to inherit from the TAction class and override some of the methods of the base class.

You must override three methods:

  • The HandlesTarget function returns whether the action object wants to handle the operation for the current target, which is by default the control with the focus.

  • The UpdateTarget procedure can set the user interface of the controls connected with the action, eventually disabling the action if the operation is currently not available.

  • You can implement the ExecuteTarget method to determine the code to execute, so that the user can select the action and doesn't have to implement it.

To show you this approach in practice, I've implemented the three cut, copy, and paste actions for a list box, in a way similar to what VCL does for an edit box (although I've simplified the code a little). I've written a base class, which inherits from the generic TListControlAction class of the ExtActns unit. This base class, TMdCustomListAction, adds some common code shared by all the specific actions and publishes a few action properties. The three derived classes have their own ExecuteTarget code, plus little more. Here are the four classes:

  TMdCustomListAction = class (TListControlAction)
    function TargetList (Target: TObject): TCustomListBox;
    function GetControl (Target: TObject): TCustomListControl;
    procedure UpdateTarget (Target: TObject); override;
    property Caption;
    property Enabled;
    property HelpContext;
    property Hint;
    property ImageIndex;
    property ListControl;
    property ShortCut;
    property SecondaryShortCuts;
    property Visible;
    property OnHint;
  TMdListCutAction = class (TMdCustomListAction)
    procedure ExecuteTarget(Target: TObject); override;
  TMdListCopyAction = class (TMdCustomListAction)
    procedure ExecuteTarget(Target: TObject); override;
  TMdListPasteAction = class (TMdCustomListAction)
    procedure UpdateTarget (Target: TObject); override;
    procedure ExecuteTarget (Target: TObject); override;

The HandlesTarget method, one of the three key methods of action classes, is provided by the TListControlAction class with this code:

function TListControlAction.HandlesTarget(Target: TObject): Boolean;
  Result := ((ListControl <> nil) or
    (ListControl = nil) and (Target is TCustomListControl)) and

The UpdateTarget method has two different implementations. The default implementation is provided by the base class and used by the copy and cut actions. These actions are enabled only if the target list box has at least one item and an item is currently selected. The status of the paste action depends on the Clipboard status:

procedure TMdCustomListAction.UpdateTarget (Target: TObject);
  Enabled := (TargetList (Target).Items.Count > 0)
    and (TargetList (Target).ItemIndex >= 0);
function TMdCustomListAction.TargetList (Target: TObject): TCustomListBox;
  Result := GetControl (Target) as TCustomListBox;
function TMdCustomListAction.GetControl(Target: TObject): TCustomListControl;
  Result := Target as TCustomListControl;
procedure TMdListPasteAction.UpdateTarget (Target: TObject);
  Enabled := Clipboard.HasFormat (CF_TEXT);

The TargetList function uses the TListControlAction class's GetControl function, which returns either the list box connected to the action at design time or the target control (the list box control with the input focus).

Finally, the three ExecuteTarget methods perform the corresponding actions on the target list box:

procedure TMdListCopyAction.ExecuteTarget (Target: TObject);
  with TargetList (Target) do
    Clipboard.AsText := Items [ItemIndex];
procedure TMdListCutAction.ExecuteTarget(Target: TObject);
  with TargetList (Target) do
    Clipboard.AsText := Items [ItemIndex];
    Items.Delete (ItemIndex);
procedure TMdListPasteAction.ExecuteTarget(Target: TObject);
  (TargetList (Target)).Items.Add (Clipboard.AsText);

Once you've written this code in a unit and added it to a package (in this case, the MdPack package), the final step is to register the new custom actions in a given category. This category is indicated as the first parameter of the RegisterActions procedure; the second parameter is the list of action classes to register:

procedure Register;
  RegisterActions ('List',
    [TMdListCutAction, TMdListCopyAction, TMdListPasteAction], nil);

To test the use of these three custom actions, I've written the ListTest example (included with the source code for this chapter). This program has two list boxes plus a toolbar that contains three buttons connected to the three custom actions and an edit box for entering new values. The program allows a user to cut, copy, and paste list box items. Nothing special, you might think—but the strange fact is that the program has no code!


To set up an image for an action (and to define default property values in general) you need to use the third parameter of the RegisterActions procedure, which is a data module hosting the image list and an action list with the predefined values. As you have to register the actions before you can set up such a data module, you'll need a double registration while developing these actions. This issue is quite complex so I won't cover it here, but a detailed description can be found on in the sections "Registering Standard Actions" and "Standard Actions And Data Modules."

Previous Section Next Section



Delphi Sources

Copyright © 2004-2024 "Delphi Sources" by BrokenByte Software. Delphi Programming Guide
ร๐๓๏๏เ ยส๎ํ๒เ๊๒ๅ   Facebook   ั๑๛๋๊เ ํเ Twitter