¿Cómo puedo crear una lista de archivos usados ​​más recientemente en Delphi 2009?

StackOverflow https://stackoverflow.com/questions/4605664

Pregunta

Tengo una TActionManager, y una TActionMainMenuBar, y sé cómo agregar un TActionClientItem para cada archivo MRU a la barra de menú principal. Pero tengo que crear una acción independiente para cada archivo en la lista MRU? ¿O hay una manera de crear una sola acción, y de alguna manera pasar una etiqueta o algo para OnExecute caso de la acción basada en la que se hizo clic en el archivo MRU?

ayuda de Delphi dice: "Para obtener más información acerca de las listas MRU, ejemplos de código, y los métodos para la búsqueda de acciones en las listas, ver FindItemByAction y FindItemByCaption en la Ayuda en línea." Pero no puedo encontrar nada en aquellos temas que es de gran ayuda, y el código ciertamente no muestra. Realmente me gustaría evitar el uso de un componente de tercera parte para conseguir este hecho.

¿Fue útil?

Solución

Vas a tener un TAction separado para cada elemento del menú de todos modos, para que puedan tener valores distintos Caption. Pero usted no tiene que tener los controladores de eventos OnExecute separadas. El controlador de eventos recibirá una referencia a la acción en su parámetro Sender. Utilice la propiedad Tag del remitente para hacer referencia a una lista donde se guardan los nombres de archivo. (No utilice la propiedad Caption para descubrir qué archivo abierto;. Que le impide hacer las cosas agradables como la adición de aceleradores o abreviando caminos difíciles de manejar)

Eso es lo que la documentación asume que haría, también. vuelve FindItemByAction el primero elemento que la acción indicada está conectada. Si adjunta una sola acción a todos los elementos de menú MRU, entonces no va a ser capaz de utilizar esa función que le diga qué menú seleccionado. Por otra parte, el elemento de menú no aguantaría más información que la acción asociada haría, así que no veo ninguna razón para tener en cuenta la opción de menú de todos modos. Sólo tiene que utilizar la información de la acción directa.

Otros consejos

Yo uso el código de la siguiente manera, pero puede que tenga que golpee en torno a algunos. Lo único que falta es muy obvio IAbbreviatedFileName que envuelve esencialmente la PathCompactPath función API de Windows. Usted querrá alguna manera de abreviar los nombres de archivo muy largo y que es mi opción preferida. Lo siento por un enorme basurero de dicho código, pero alguien puede encontrar algo de su uso dentro de!

type
  TFileAwareMenuItem = class(TMenuItem)
  private
    FFileName: string;
  public
    property FileName: string read FFileName write FFilename;
  end;

  TMRU = class
  private
    FParent: array of TMenuItem;
    FMenuItemStart: array of TMenuItem;
    FMenuItemFinish: array of TMenuItem;
    FMenuCount: Integer;
    FRegistryKey: string;
    FOwner: TCustomForm;
    FMRUFileNames: TStringList;
    FAction: TAction;
    function GetCount: Integer;
    function GetItem(Index: Integer): string;
    procedure SetAction(Value: TAction);
    procedure Read;
    procedure Write;
    procedure UpdateMenu;
  public
    constructor Create(const RegistrySubKey: string; const Owner: TCustomForm);
    destructor Destroy; override;
    procedure RegisterBoundingMenuItems(Start, Finish: TMenuItem);
    procedure Add(const FileName: string);
    procedure Delete(ItemNum: Integer);
    property Count: Integer read GetCount;
    property Action: TAction read FAction write SetAction;
    property Items[Index: Integer]: string read GetItem; default;
  end;

const
  MRUSize=9;
  AppRegistryKey='??put your apps registry key here??';

var
  Registry: TRegistry;

constructor TMRU.Create(const RegistrySubKey: string; const Owner: TCustomForm);
begin
  inherited Create;
  FRegistryKey := Format('%s\%s', [AppRegistryKey, RegistrySubKey]);
  FOwner := Owner;
  FMRUFileNames := TStringList.Create;
  Read;
end;

destructor TMRU.Destroy;
begin
  Write;
  FreeAndNil(FMRUFileNames);
  inherited;
end;

procedure TMRU.RegisterBoundingMenuItems(Start, Finish: TMenuItem);
begin
  inc(FMenuCount);
  SetLength(FParent, FMenuCount);
  SetLength(FMenuItemStart, FMenuCount);
  SetLength(FMenuItemFinish, FMenuCount);

  FMenuItemStart[FMenuCount-1] := Start;
  FMenuItemFinish[FMenuCount-1] := Finish;
  Assert(Start.Parent=Finish.Parent);
  FParent[FMenuCount-1] := Start.Parent;

  UpdateMenu;
end;

procedure TMRU.UpdateMenu;
var
  Intf: IAbbreviatedFileName;
  i, j: Integer;
  FileName: string;
  NewMenuItem: TFileAwareMenuItem;
begin
  Intf := FOwner as IAbbreviatedFileName;
  for i := 0 to FMenuCount-1 do begin
    j := FMenuItemStart[i].MenuIndex+1;
    while j<FMenuItemFinish[i].MenuIndex do begin
      FParent[i][j].Free;
    end;
    for j := 0 to Count-1 do begin
      NewMenuItem := TFileAwareMenuItem.Create(FMenuItemStart[i].Owner);
      NewMenuItem.Action := Action;
      NewMenuItem.FileName := FMRUFileNames[j];
      FileName := ReplaceString(Intf.AbbreviatedFileName(NewMenuItem.FileName, False), '&', '&&');
      NewMenuItem.Caption := Format('&%d. %s', [j+1, FileName]);
      FParent[i].Insert(FMenuItemFinish[i].MenuIndex, NewMenuItem);
    end;
    FMenuItemStart[i].Visible := (Count>0) and (FMenuItemStart[i].MenuIndex>0);
    FMenuItemFinish[i].Visible := (FMenuItemFinish[i].MenuIndex<FParent[i].Count-1);
  end;
end;

procedure TMRU.Read;
var
  i: Integer;
  s: string;
begin
  if Registry.OpenKey(HKEY_CURRENT_USER, FRegistryKey) then begin
    FMRUFileNames.Clear;
    for i := 0 to MRUSize-1 do begin
      s := Registry.ReadString(IntToStr(i+1), '');
      if s<>'' then begin
        FMRUFileNames.Add(s);
      end;
    end;
    UpdateMenu;
    Registry.CloseKey;
  end;
end;

procedure TMRU.Write;
var
  i: Integer;
  ValueName: string;
begin
  if Registry.OpenKey(HKEY_CURRENT_USER, FRegistryKey, KEY_ALL_ACCESS, True) then begin
    Registry.WriteInteger('Size', MRUSize);
    for i := 0 to MRUSize-1 do begin
      ValueName := IntToStr(i+1);
      if i<Count then begin
        Registry.WriteString(ValueName, FMRUFileNames.Strings[i]);
      end else begin
        if Registry.ValueExists(ValueName) then begin
          Registry.DeleteValue(ValueName);
        end;
      end;
    end;
    Registry.CloseKey;
  end;
end;

function TMRU.GetCount: Integer;
begin
  Result := Min(FMRUFileNames.Count, MRUSize);
end;

function TMRU.GetItem(Index: Integer): string;
begin
  Result := FMRUFileNames[Index];
end;

procedure TMRU.SetAction(Value: TAction);
begin
  if Value<>FAction then begin
    FAction := Value;
    UpdateMenu;
  end;
end;

procedure TMRU.Add(const FileName: string);
var
  i, Index: Integer;
begin
  Index := -1;
  for i := 0 to FMRUFileNames.Count-1 do begin
    if FileNamesEqual(FileName, FMRUFileNames[i]) then begin
      Index := i;
      break;
    end;
  end;

  if Index<>-1 then begin
    FMRUFileNames.Move(Index, 0);
  end else begin
    FMRUFileNames.Insert(0, FileName);
    if FMRUFileNames.Count>MRUSize then begin
      FMRUFileNames.Delete(FMRUFileNames.Count-1);
    end;
  end;

  UpdateMenu;
  Write;
end;

procedure TMRU.Delete(ItemNum: Integer);
begin
  FMRUFileNames.Delete(ItemNum);
  UpdateMenu;
end;

initialization
  Registry := TRegistry.Create;
  if not Registry.KeyExists(AppRegistryKey) then begin
    Registry.CreateKey(AppRegistryKey);
  end;

finalization
  FreeAndNil(Registry);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top