Wie kann ich eine zuletzt verwendete Dateiliste in Delphi 2009 erstellen?
-
25-09-2019 - |
Frage
Ich habe eine TActionManager und ein TActionMainMenuBar, und ich weiß, wie man eine TActionClientItem für jede MRU-Datei in der Hauptmenüleiste hinzuzufügen. Aber habe ich eine separate Aktion für jede MRU-Datei in der Liste erstellen? Oder ist es eine Möglichkeit, nur eine Aktion zu erstellen, und irgendwie einen Tag oder etwas zu dem Ereignis OnExecute Basis der Aktion übergeben, auf der MRU-Datei geklickt wurde?
Delphi Hilfe sagt: „Für weitere Informationen über MRU-Listen, Beispielcode und Methoden für die Aktionen in Listen zu finden, finden Sie FindItemByAction und FindItemByCaption in der Online-Hilfe.“ Aber ich kann nicht alles in diesen Themen finden, die hilfreich ist, und schon gar nicht Beispielcode. Ich möchte wirklich vermeiden, dass eine dritte Partei Komponente dieses zu erhalten getan.
Lösung
Sie werden über einen separaten TAction
zu jedem Menüpunkt haben ohnehin so, dass sie unterschiedliche Caption
Werte haben können. Aber Sie haben keine separaten OnExecute
Event-Handler haben. Der Event-Handler wird einen Verweis auf die Aktion in seinen Sender
Parametern erhalten. Verwenden Sie die Tag
Eigenschaft des Absenders in einer Liste, in der die Dateinamen gehalten werden verweisen. (Verwenden Sie die Caption
Eigenschaft nicht, welche Datei geöffnet zu entdecken,., Dass einengt Sie tun nette Dinge wie Beschleuniger Hinzufügen oder Abkürzen unhandlich Pfade)
Das ist, was die Dokumentation setzt voraus, würden Sie auch tun. FindItemByAction
kehrt die erste Element, dass die gegebene Aktion ist an. Wenn Sie eine einzelne Aktion auf alle Ihre MRU Menüpunkte anbringen, dann werden Sie nicht in der Lage sein, diese Funktion zu verwenden, um Ihnen zu sagen, welches Menü ausgewählt wurde. Auf der anderen Seite würde der Menüpunkt nicht hält mehr Informationen als die damit verbundene Aktion würde, so dass ich keinen Grund zu sehen für den Menüpunkt sowieso sehen. Verwenden Sie einfach die Informationen aus der Aktion direkt an.
Andere Tipps
Ich verwende Code wie folgt, aber man kann es sich um einige klopfen müssen. Das einzige, was fehlt, sehr offensichtlich ist IAbbreviatedFileName
, die im Wesentlichen der Windows-API-Funktion PathCompactPath
einpackt. Sie werden eine Möglichkeit, sehr lange Dateinamen abkürzen wollen und das ist meine bevorzugte Wahl. Es tut uns so großen Dump-Code, aber jemand kann etwas Gebrauch innerhalb finden!
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);