2011-01-05 3 views
3

Ich habe einen TActionManager und eine TActionMainMenuBar, und ich weiß, wie man ein TActionClientItem für jede MRU-Datei zur Hauptmenüleiste hinzufügt. Muss ich für jede MRU-Datei in der Liste eine separate Aktion erstellen? Oder gibt es eine Möglichkeit, nur eine Aktion zu erstellen und irgendwie ein Tag oder etwas an das OnExecute-Ereignis der Aktion zu übergeben, basierend darauf, auf welche MRU-Datei geklickt wurde?Wie kann ich eine zuletzt verwendete Dateiliste in Delphi 2009 erstellen?

Delphis Hilfe sagt: "Weitere Informationen zu MRU-Listen, Beispielcode und Methoden zum Suchen von Aktionen in Listen finden Sie unter FindItemByAction und FindItemByCaption in der Online-Hilfe." Aber ich kann nichts in diesen Themen finden, das hilfreich ist, und sicherlich nicht Beispielcode. Ich möchte wirklich vermeiden, eine Komponente von Drittanbietern zu verwenden, um dies zu tun.

+1

lauern mehr, Demos \ DelphiWin32 \ VCLWin32 \ ActionBands \ MRU \ ABMRU.dpr –

+0

fand ich, dass nach der Frage der Veröffentlichung, aber nach dem Kompilieren und die Demo läuft, ist es ein wenig fehlerhaft zu sein scheint, so dass ich Ich bin mir nicht sicher .... – croceldon

Antwort

3

Sie haben für jedes Menüelement eine separate TAction, so dass sie verschiedene Caption Werte haben können. Sie müssen jedoch keine separaten OnExecute Event-Handler haben. Der Event-Handler erhält in seinem Parameter Sender einen Verweis auf die Aktion. Verwenden Sie die Eigenschaft Tag des Absenders, um auf eine Liste zu verweisen, in der Ihre Dateinamen gespeichert sind. (Verwenden Sie nicht die Caption -Eigenschaft, um zu ermitteln, welche Datei geöffnet werden soll. Dadurch können Sie keine schönen Dinge wie Beschleuniger hinzufügen oder unhandliche Pfade umgehen.)

Das wird in der Dokumentation auch vorausgesetzt FindItemByAction gibt den ersten -Eintrag zurück, an den die angegebene Aktion angehängt ist. Wenn Sie eine einzelne Aktion an alle MRU-Menüelemente anhängen, können Sie diese Funktion nicht verwenden, um Ihnen mitzuteilen, welches Menü ausgewählt wurde. Auf der anderen Seite würde der Menüeintrag nicht mehr Informationen enthalten als die zugehörige Aktion, so dass ich keinen Grund sehe, den Menüeintrag trotzdem zu suchen. Verwenden Sie einfach die Informationen aus der Aktion direkt.

4

Ich benutze Code wie folgt, aber Sie müssen möglicherweise einige klopfen. Das einzige, was ganz offensichtlich fehlt, ist IAbbreviatedFileName, das im Wesentlichen die Windows-API-Funktion PathCompactPath umschließt. Sie werden eine Möglichkeit finden, sehr lange Dateinamen zu verkürzen, und das ist meine bevorzugte Wahl. Entschuldigung für solch einen riesigen Code-Dump, aber irgendwer könnte etwas Nützliches darin 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); 
+0

Hallo, ich habe mir den obigen Code angesehen und mich gefragt, wie ich den obigen Code implementiere, um ein erneutes Menü auf einer ActionMainMenuBar zu erstellen? Ich brauche es, um die Einstellungen von einer Ini-Datei zu lesen, anstatt die Registrierung, die ich in der Lage sein kann, zu erarbeiten, kann ich nicht herausfinden, wie man es implementiert? jede Hilfe wäre toll – colin

+0

Ich weiß nicht, was eine ActionMainMenuBar ist. Wie auch immer, gehen Sie selbst und stellen Sie eine Frage, wenn Sie nicht weiterkommen. –

+0

ok vielen Dank – colin

Verwandte Themen