Executing Commands

The Ribbon Framework provides access to the commands you defined in the Ribbon Designer. You do not have access to ribbon controls however. You can customize certain properties of commands at run-time, such as the caption, images and whether the command is enabled.

The TUIRibbon.Commands property provides access to all currently created commands. With "currently created" I mean that commands are only added to this collection when the Ribbon Framework creates it. The framework will only create it when it is needed for the first time. For example, the commands visible on the ribbon are usually created immediately when the ribbon is loaded. However, commands that are available in submenus (such as the application menu or drop-down menus) are only created the first time that menu is opened by the user.

Command Classes

All commands derive from the abstract base class TUICommand, which has the following properties:

  • Tag: a user definable tag for the command. Similar to the Tag property of Delphi controls.
  • CommandId: the numeric identifier of the command. You can specify this number in the Ribbon Designer, or - if you don't - let the Ribbon Compiler assign a command Id. For each command, the Ribbon Designer will add a constant with this value to a Pascal file that is generated when you build or preview the Ribbon in the Ribbon Designer.
  • Enabled: whether the command is currently enabled.
  • Caption*: the caption of the command.
  • Keytip*: the keytip to use for this command.
  • Shortcut: a keyboard shortcut that can be used to execute this command. You cannot assign keyboard shortcuts with the Ribbon Designer, but you can assign them at run-time using this property.
  • TooltipTitle*: the title of the tooltip for this command.
  • TooltipDescription*: the description of the tooltip for this command.
  • LargeImage*: the currently used large image to display when the button/control for this command is rendered in Large mode.
  • SmallImage*: the currently used small image to display when the button/control for this command is rendered in Small mode.
  • LargeHighContrastImage*, SmallHighContrastImage*: as LargeImage and SmallImage, but contains images to be displayed when Windows is running in High-Contrast mode.
  • ActionLink: allows you to link the command to a Delphi TAction component. More on this later.

*: These properties are not initialized when the command is created, because the Ribbon Framework doesn't provide this information. So initially, these properties will be empty. You can change these properties however, and once you have done so, reading the property will return the new value.

The Image properties are of type TUIImage. This class allows you to load images from BMP or PNG files or resources. This will be discussed later when we populate the List Style gallery.

Every command in a ribbon application is of a type derived from TUICommand. The actual command class that is used depends on how the command is used by the ribbon (whether it is used as a button, a font control, a check box etc.). These are all the command classes and the controls they are used for:

Command Class Ribbon Controls
TUICommandGroup* Groups on a Ribbon Tab
TUICommandAction Buttons and the Help Button
TUICommandCollection Drop-Down Galleries, Split Button Galleries, In-Ribbon Galleries, Combo Boxes and the Quick Access Toolbar
TUICommandDecimal Spinner Control
TUICommandBoolean Toggle Buttons and Check Boxes
TUICommandAnchor* Application Menu, Drop-Down Buttons, Split Buttons and Tabs
TUICommandContext Contextual tab groups
TUICommandFont Font Control
TUICommandColorAnchor   Drop-Down Color Picker
TUICommandRecentItems Recent Items list in the Application Menu

*: these command classes provide no additional properties or events in addition to the TUICommand base class.

Accessing Commands

You can access commands in the Ribbon Framework by command ID. The Ribbon Designer created a Pascal file with all Command IDs for us. You need to add this file to your project. In our TextPad example, we need to add the file "Ribbon\RibbonMarkup.pas" to the project. For each command you specified in the Ribbon Designer, you will find a constant in this unit. For example, the unit may look like this (only partially shown):

The Generated RibbonMarkup.pas file
unit RibbonMarkup;

// *****************************************************************************
// * This is an automatically generated source file for UI Element definition  *
// * resource symbols and values. Please do not modify manually.               *
// *****************************************************************************

interface

const
  CmdTabHome = 2;
  CmdGroupClipboard = 3;
  CmdPaste = 4;
  CmdPasteSpecial = 5;
  CmdPasteMore = 6;
  CmdCut = 7;
  CmdCopy = 8;

implementation

end.

The name of each constant matches the Command Name you specified in the Ribbon Designer, unless you also specified a Symbol Name, in which case that name is used. Add the RibbonMarkup unit to the uses-clause of the main form.

The safest way to access and initialize these commands is by overriding the CommandCreated method in the main form. For example, you can access the Cut, Copy and Paste commands like this:

Linking to Commands
procedure TFormMain.CommandCreated(const Sender: TUIRibbon;
  const Command: TUICommand);
begin
  inherited;
  case Command.CommandId of
    CmdPaste:
      begin
        FCmdPaste := Command as TUICommandAction;
        FCmdPaste.OnExecute := PasteExecute;
      end;

    CmdPasteSpecial:
      begin
        FCmdPasteSpecial := Command as TUICommandAction;
        FCmdPasteSpecial.SetShortCut([ssCtrl, ssAlt], 'V');
        FCmdPasteSpecial.OnExecute := NotImplemented;
      end;

    CmdCut:
      begin
        FCmdCut := Command as TUICommandAction;
        FCmdCut.OnExecute := CutExecute;
      end;

    CmdCopy:
      begin
        FCmdCopy := Command as TUICommandAction;
        FCmdCopy.OnExecute := CopyExecute;
      end;
  end;
end;

In the code above, you will see that we assign the shortcut Ctrl+Alt+V to the Paste Special command. We cannot specify shortcuts in the ribbon markup (or with the Ribbon Designer), so we have to do that at run-time. You can also use the ShortCut property instead of the SetShortCut method. Note that we don't set shortcuts for the Cut, Copy and Paste commands, because the TRichEdit control handles these shortcuts natively.

Linking Commands to Actions

Since version 1.1 of the library, you can also link commands to standard Delphi actions. Every command has an ActionLink property that you can use for this. Set its Action property to the action you want to link to, like in the following example:

Linking to Commands
procedure TFormMain.CommandCreated(const Sender: TUIRibbon;
  const Command: TUICommand);
begin
  inherited;
  case Command.CommandId of
    CmdPaste:
      begin
        FCmdPaste := Command as TUICommandAction;
        FCmdPaste.ActionLink.Action := ActionPaste;
      end;

    CmdPasteSpecial:
      begin
        FCmdPasteSpecial := Command as TUICommandAction;
        FCmdPasteSpecial.SetShortCut([ssCtrl, ssAlt], 'V');
        FCmdPasteSpecial.ActionLink.Action := ActionNotImplemented;
      end;

    CmdCut:
      begin
        FCmdCut := Command as TUICommandAction;
        FCmdCut.ActionLink.Action := ActionCut;
      end;

    CmdCopy:
      begin
        FCmdCopy := Command as TUICommandAction;
        FCmdCopy.ActionLink.Action := ActionCopy;
      end;
  end;
end;

Then, the given action will be executed when the command is executed. This way, you can use the same action in both the ribbon and other VCL controls. For an example that uses this approach, see the "Text Pad with Action List" sample application in the download.

TUICommandAction

Since the Cut, Copy and Paste commands in the examples above are represented by regular buttons, they are implemented in objects of type TUICommandAction. This class has an OnExecute event that is fired when the user clicks the button. The OnExecute event for the Paste command may look like this:

OnExecute for the Paste command
procedure TFormMain.PasteExecute(const Args: TUICommandActionEventArgs);
begin
  RichEdit.PasteFromClipboard;
end;

This example assumes that you have added a TRichEdit control to the main form called RichEdit. You should set its Align property to alClient so it takes up the entire space of the form that is not occupied by the Ribbon.

Each event has a single record parameter called Args. The type of this parameter depends on the type of command, but all Args records share at least these fields:

  • Command: the command that originated the event (similar to the Sender parameter in common Delphi events).
  • Verb: how the action should be performed. The Verb can have 3 values:
    • cvExecute: execute the command normally.
    • cvPreview: preview the result of the command.
    • cvCancelPreview: cancel the preview and revert to the state before the preview.
  • Properties: additional properties for the event. You only need this in special cases.

The Verb field is mostly used in combination with Galleries. For example, in Word 2010, when you hover the mouse over an item in a gallery, the command is executed in cvPreview mode. In that case, Word will show a preview of what the Word document will look like when the gallery item would be applied. When the user moves the mouse away from the gallery, the command is executed in cvCancelPreview mode. Word will revert the document view back to how it was before the gallery item was selected. Finally, when the user clicks the item in the gallery, the command will be executed in cvExecute mode. This will lock in the selection and update the document.

In many cases, you do not care about the value of the Verb field, and you can implement the event as though cvExecute was used.

BTW: If you prefer, you can assign the same event to multiple commands. Then, in the event handler, you would check the command or command ID and take the appropriate action. For example, you could implement the Cut, Copy and Paste functionality in a single event like this:

Single OnExecute for all clipboard commands
procedure TFormMain.ClipboardExecute(const Args: TUICommandActionEventArgs);
begin
  case Args.Command.CommandId of
    CmdPaste: RichEdit.PasteFromClipboard;
    CmdCopy : RichEdit.CopyToClipboard;
    CmdCut  : RichEdit.CutToClipboard;
  end;
end;

Next we will look at some other command types.

Next: Other Command Types