tags:

views:

129

answers:

1

This adds an ActionClientItem at runtime from a stringList:

var
  ActionClient: TActionClient;
  ChildItem: TActionClientItem;
if FileExists( ARecentFilesFilename ) then
begin
  ARecentFilesList.LoadFromFile( ARecentFilesFilename );
  // remove any duplicates
  RemoveDuplicates( ARecentFilesList );
  for i := 0 to ARecentFilesList.Count - 1 do
    begin
      Ribbon1.AddRecentItem( ARecentFilesList.Strings[ i ] );
      ActionClient := RibbonGroup1.ActionControls[ 1 ].ActionClient;
      ChildItem := ActionClient.Items.Add;
      ChildItem.Tag := i;
      ChildItem.Action := ActionOpenFileFromButton1;
      ChildItem.Caption := ARecentFilesList.Strings[ i ];
    end;
end;

This attempts to get the filename of the selected ActionClientItem but it fails.

procedure TMainForm.ActionOpenFileFromButton1Execute( Sender: TObject );
var
  ActionClient: TActionClient;
  ChildItem: TActionClientItem;
  AFilename: string;
  AIndex: integer;
begin
  ActionClient := RibbonGroup1.ActionControls[ 1 ].ActionClient;
  AIndex := ActionClient.Index;
  ChildItem := ActionClient.Items.ActionClients[ AIndex ];
  AFilename := ChildItem.Caption;
  OpenZipFileFromChildButton( AFilename );
end;

What am I doing wrong? Is there a different way do do this?

+1  A: 

You can use the Sender to get access to the filename, but it's a TAction, so you need to have one action per recent file. Add them to your ActionManager and also keep a reference to them in a list.

edit

If you don't have a TActionManager on your form, drop one on there and associate it with the ribbon. Then, create say 10 actions, calling them RecentFileAction1, RecentFileAction2, etc. Then, in the form's OnCreate event handler, add them to your FRecentFileActions list:

TMainForm = class (TForm)

  //...

private
  FRecentFileActions: TList<TAction>;

  //...

end;


procedure TMainForm.FormCreate(ASender: TOject);
begin
  FRecentFileActions := TList<TAction>.Create;

  FRecentFileActions.Add(RecentFileAction1);
  FRecentFileActions.Add(RecentFileAction2);
  FRecentFileActions.Add(RecentFileAction3);
  // etc

  LoadRecentFilenames;
  RefreshActions;

end;

/edit

Then, change the caption on each action to the filename of the file.

procedure TMainForm.RefreshActions;
var
  i: integer;
begin
  for i := 0 to FRecentFileList.Count - 1 do
  begin     
    if i < FRecentFileActions.Count then
      FRecentFileActions[i].Caption := FRecentFileList[i];
  end;
end;

So, in the end, your event handler could look like this:

procedure TMainForm.ActionOpenFileFromButton1Execute( Sender: TObject );
var
  LAction: TAction;
begin
  LAction := Sender as TAction;
  OpenZipFileFromChildButton(LAction.Caption);
end;

N@

Nat
+1 Definitely the way to go. I may create a TMRUAction or something like that, that keeps the full file path in a property, but your basic strategy is spot-on.
Cobus Kruger
After spending a second full day on this I still can not get the index or caption of the selected action in my demo. if FRecentFileActions is a TAction you can not interate through it because TAction only has one caption per action. Do you have to use an Actionlist or the ActionManager to do this?if i < FRecentFileActions.Count then FRecentFileActions[i].Caption := FRecentFileList[i];My demo is a simple D2010 project with only vcl components. If you are interested in assisting me, can I email you my demo?Bill
Bill Miller
Yes, you need an ActionManager or a ActionList. I assumed you had an ActionManager since you seemed to be using a Ribbon. See my new edit at the top of my answer.
Nat
Yes I have an ActionManager... but sorry...:varFRecentFileActions: TAction;procedure TMainForm.RefreshActions;var i: integer;begin for i := 0 to FRecentFileList.Count - 1 do begin if i < FRecentFileActions.Count then FRecentFileActions[i].Caption := FRecentFileList[i]; end;end;will not even compile if FRecentFileActions is a TAction. There must be more variables defined for this to compile.
Bill Miller
FRecentFileActions is not a TAction. It is a Generic TList<T>, instantiated as a list of TActions... So it is "FRecentFileActions: TList<TAction>", exactly as I typed in my answer. You have to have Generics.Collections in your uses clause.
Nat
Thanks Nat,I finally have it working. Bill
Bill Miller