Contributor: ROBERT MARSH
unit MRUFList;
(* Implements a Recently-Used Files List *)
(* Constructed by Robert R. Marsh, S.J., 1995 *)
(* Use freely, distribute widely, charge nothing*)
(* If you like it you could always give some *)
(* money to your favorite charity. *)
(* Comments, bug-reports, praise and blame to: *)
(* RobMarsh@AOL.COM *)
interface
uses
 SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
 Forms, Dialogs, Menus, IniFiles;
type
 TRecentFileEvent = procedure(Sender: TObject; LatestFile: string) of object;
type
 TRecentFiles = class(TComponent)
 private
 FMenu : TMenuItem;
 Divider : TMenuItem;
 FMaxFiles : integer;
 FIniFileName: string;
 FLatestFile : string;
 FOnClick : TRecentFileEvent;
 procedure SetLatestFile(value: string);
 procedure SetMenu(value: TMenuItem);
 procedure SetMaxFiles(value: integer);
 procedure MenuOnClick(Sender: TObject);
 function DividerPlace: integer;
 protected
 procedure Click(RecentFile: string);
 public
 constructor Create(AOwner: TComponent); override;
 procedure SaveToIniFile;
 procedure LoadFromIniFile;
 property LatestFile: string read FLatestFile write SetLatestFile;
 published
 property Menu : TMenuItem read FMenu write SetMenu;
 property MaxFiles : integer read FMaxFiles write SetMaxFiles;
 property IniFileName: string read FIniFileName write FIniFileName;
 property OnClick : TRecentFileEvent read FOnClick write FOnClick;
 end;
procedure Register;
implementation
procedure Register;
begin
 RegisterComponents('Mine', [TRecentFiles]);
end;
{we frequently need to know both if the Divider}
{has been added and, if so, where it is}
function TRecentFiles.DividerPlace: integer;
begin
Result:=-1;
if FMenu  nil then
 begin
 Result:=Menu.IndexOf(Divider);
 end;
end;
procedure TRecentFiles.SetMenu(value: TMenuItem);
begin
FMenu:=value;
end;
procedure TRecentFiles.SetMaxFiles(value: integer);
var
 n: integer;
begin
{the Max value of MaxFiles is 9}
if value <=9 then begin FMaxFiles:=value; end else begin FMaxFiles:=9; end; if (FMenu  nil) and (DividerPlace  -1) then
 begin
 {trim off any entries more MaxFiles}
 while Menu.Count> DividerPlace + FMaxFiles + 1 do
 begin
 Menu.Delete(Menu.Count-1);
 end;
 {if neccesary delete the divider too}
 if FMaxFiles = 0 then
 begin
 Menu.Delete(Menu.Count-1);
 end;
 end;
end;
procedure TRecentFiles.SetLatestFile(value: string);
var
 NewMenuItem: TMenuItem;
 n : integer;
 Thiscaption: string;
 OldPlace : integer;
 DividerPos : integer;
begin
FLatestFile:=value;
if (Menu  nil) and (MaxFiles> 0) and
 (FLatestFile  '') then
 begin
 {special case - the divider}
 if DividerPlace < 0 then begin Menu.Add(Divider); end; {is the new Name already there?} DividerPos:=DividerPlace; n:=DividerPos+1; while (n < Menu.Count) do begin if FLatestFile = Copy(Menu.Items[n].Caption,4,high(string)) then begin OldPlace:=n; Break; end else begin inc(n); end; end; if n>= Menu.Count then {we add}
 begin
 NewMenuItem:=TMenuItem.Create(Self);
 NewMenuItem.Caption:='&1 '+FLatestFile;
 {what happens if we click it}
 NewMenuItem.OnClick:=MenuOnClick;
 Menu.Insert(DividerPos+1,NewMenuItem);
 end
 else {we insert}
 begin
 NewMenuItem:=Menu.Items[OldPlace];
 Menu.Delete(OldPlace);
 Menu.Insert(DividerPos+1,NewMenuItem);
 end;
 {now change the 'hot' keys}
 for n:=DividerPos+1 to Menu.Count - 1 do
 begin
 ThisCaption:=Menu.Items[n].Caption;
 ThisCaption[2]:=Chr(n - DividerPos + Ord('1') -1);
 Menu.Items[n].Caption:=ThisCaption;
 end;
 {delete any excess items}
 if Menu.Count> DividerPos + MaxFiles + 1 then
 begin
 Menu.Delete(Menu.Count-1);
 end;
 end;
end;
procedure TRecentFiles.Click(RecentFile: string);
begin
if Assigned(FOnClick) then FOnClick(Self,RecentFile);
end;
procedure TRecentFiles.SaveToIniFile;
var
 IniFile : TIniFile;
 n : integer;
 DividerPos: integer;
begin
if Menu  nil then
 begin
 {if this property is blank we use the default}
 if IniFileName = '' then
 begin
 IniFileName:=ChangeFileExt(ExtractFileName(Application.ExeName),'.INI')
 end;
 IniFile:=TIniFile.Create(IniFileName);
 IniFile.EraseSection('FileHistory');
 IniFile.WriteInteger('FileHistory','MaxFiles',MaxFiles);
 if (Menu  nil) and (DividerPlace  -1) then
 begin
 DividerPos:=DividerPlace;
 n:=DividerPos+1;
 while n < Menu.Count do begin IniFile.WriteString('FileHistory','File'+Chr(n+Ord('1')-1-DividerPos),Copy(Menu.Items[n].Caption,4,high(string))); inc(n); end; IniFile.Free; end; end; end; procedure TRecentFiles.LoadFromIniFile; var IniFile: TIniFile; n : integer; Name : string; begin if Menu  nil then
 begin
 if IniFileName = '' then
 begin
 IniFileName:=ChangeFileExt(ExtractFileName(Application.ExeName),'.INI')
 end;
 IniFile:=TIniFile.Create(IniFileName);
 MaxFiles:=0;
 MaxFiles:=IniFile.ReadInteger('FileHistory','MaxFiles',MaxFiles);
 n:=1;
 while true do
 begin
 Name:=IniFile.ReadString('FileHistory','File'+Chr(n+Ord('1')-1),'');
 if Name = '' then
 begin
 Break;
 end;
 LatestFile:=Name;
 inc(n);
 end;
 end;
end;
constructor TRecentFiles.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FMaxFiles:=0;
FMenu:=nil;
Divider:=TMenuItem.Create(Self);
Divider.Caption:='-';
end;
procedure TRecentFiles.MenuOnClick(Sender: TObject);
var
 Name: string;
begin
 begin
 Name:=Copy(TMenuItem(Sender).Caption,4,high(string));
 Click(Name);
 end;
end;
end.


AltStyle によって変換されたページ (->オリジナル) /