Question

I have a form with most of its functionality implemented using standard TAction. I have a menu, a toolbar, and some toobuttons. I have implemented clipboard copy/paste with no code at all, just using TEditCopy and TEditPaste actions. It works perfect in the TEdit and TMemo boxes I have.

Now, I want it to work with TListBox, too. Specifically, I want to be able to copy the selected list item in a TListBox using the very same menuitems, key shortcuts and toolbuttons.

So, I believe I will need to extend the TEditCopy Action. But it doesn't seem very straight forward to me. In particular, the TEditAction checks for the focused control to be a TCustomEdit control, which a TListBox it is not. I am a little afraid that it will be just too much work.

The obvious alternative is to just forget about the standard actions and implement the copy to clipbard in the OnExecute method of a generic TAction.

But, before giving up, do you have some idea, hint or trick that would help me extend the standard TEditCopy action?

Was it helpful?

Solution

You should either override the event handlers of a TAction or create a new descendant that combines the code from TEditAction/TEditCopy with the extra handling for TListBox.

The extension point for actions is setting the OnExecute/OnUpdate event handlers, and that won't work here because it would disable the existing TEdit handling. You could descend from TEditCopy and override the methods, but it would probably be as much code as a new class that descended straight from TAction. There might be some other low-level hack that would work, but I don't see it, and even if there were, it's guaranteed to be less maintainable than the documented approach.

OTHER TIPS

Here is the hack I came out to implement.

It does not require to manually change the ActionList or the MenuItems and ToolButtons I already have, because I keep the same name TEditCopy for the class.

type
 TEditCopy = class(StdActns.TEditCopy)
  public
   function HandlesTarget(Target: TObject): Boolean; override;
   procedure ExecuteTarget(Target: TObject); override;
   procedure UpdateTarget(Target: TObject); override;
  end;

It extends the standard TEditCopy action with the required functionality of supporting TListBox as well.

function TEditCopy.HandlesTarget(Target: TObject): Boolean;
 begin
  result:=(inherited handlesTarget(Target)) or (target is TListbox);
 end;

procedure TEditCopy.ExecuteTarget(Target: TObject);
 begin
  if (target is TListBox) and (TListBox(Target).ItemIndex<>-1) then
    clipboard.AsText:=TListBox(Target).Items[TListBox(Target).ItemIndex]
  else
    inherited;
 end;

procedure TEditCopy.UpdateTarget(Target: TObject);
 begin
  if target is TListbox then
    Enabled := true
  else
    inherited;
 end;

The rest of the application is unchanged. All the copy/paste functionalit is still implemented with no code at all.

I remember having read something on the web about it, but I can't find the link back. If I find it back, I'll tell you more precisely about it.

What I remember, though, is that an action checks wether it can be applied (or not) to a particular target using the "TBasiAction.HandlesTarget" method - which is virtual. You should check how the methods "HandlesTarget", "UpdateTarget" and "ExecuteTarget" (all members of TBasicAction) are used when executing an Action.

Again, more about this if I find the link back.

[Edit]

This wasn't the post I was looking for, but it seems to describe exactly what you want : etutorials : Defining Custom Actions

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top