Mega Code Archive

 
Categories / Delphi / VCL
 

Mrulist-recentfiles [component]

//www.dronymc.cjb.net //drony@mynet.com //icq:266148308 {Programınız ile daha önceden açtığınız dosyayı tekrar açmnınızı sağlar kayıtları ini dosyaseında tutat} unit MruUnit; interface uses Windows, Messages, SysUtils, Classes, Forms, Menus, IniFiles, Registry; type TMRUMenuEvent = procedure (Sender: TObject; const Filename: string) of Object; TMostRecentFiles = class(TComponent) private fMaxFiles: cardinal; fMenuPosition: cardinal; fOwnerMenuItem: TMenuItem; fIniFilename: string; fRegPath: string; fShowFullPath: boolean; fFileList: TStrings; fMRUClickEvent: TMRUMenuEvent; fNoFileEvent: TMRUMenuEvent; procedure SetMaxFiles(count: cardinal); procedure SetShowFullPath(value: boolean); procedure LoadFilesFromReg; procedure LoadFilesFromIni; procedure SaveFilesToReg; procedure SaveFilesToIni; procedure SetIniFile(const aIniFile: string); procedure SetRegPath(const aRegPath: string); procedure SetOwnerMenu(aMenuItem: TMenuItem); protected procedure DoClick(Sender: TObject); procedure RefreshList; procedure Loaded; override; procedure Notification(AComponent: TComponent; Operation: TOperation); override; public constructor Create(aOwner: TComponent); override; destructor Destroy; override; //include a call to this method where ever a file is opened ... function AddFile(const Filename: string): boolean; published property MaxFiles: cardinal read fMaxFiles write SetMaxFiles; {1..8} property ShowFullPath: boolean read fShowFullPath write SetShowFullPath; //the MRU list has to be attached somewhere ... property OwnerMenuItem: TMenuItem read fOwnerMenuItem write SetOwnerMenu; property MenuPosition: cardinal read fMenuPosition write fMenuPosition; //store the list either in an ini file or in the registry ... property IniFile: string read fIniFilename write SetIniFile; property RegPath: string read fRegPath write SetRegPath; //feedback an MRU menuItem click by assigning this event ... property OnMenuClick: TMRUMenuEvent read fMRUClickEvent write fMRUClickEvent; //optional event triggered whenever a clicked MRU file no longer exists... property OnFileNotExist: TMRUMenuEvent read fNoFileEvent write fNoFileEvent; end; procedure Register; const MRU_FLAG = $BAD1DEA; implementation resourceString s_no_file_exists = 'The file ...'#10'"%s"'#10'no longer exists.'; procedure Register; begin RegisterComponents('Plus', [TMostRecentFiles]); end; //------------------------------------------------------------------------------ constructor TMostRecentFiles.Create(aOwner: TComponent); begin inherited Create(aOwner); fFileList := TStringList.create; fMaxFiles := 4; end; //------------------------------------------------------------------------------ destructor TMostRecentFiles.Destroy; begin if not (csDesigning in ComponentState) then try if fRegPath = '' then SaveFilesToIni else SaveFilesToReg; except end; fFileList.free; inherited Destroy; end; //------------------------------------------------------------------------------ procedure TMostRecentFiles.Loaded; begin inherited Loaded; if not (csDesigning in ComponentState) then if fRegPath = '' then LoadFilesFromIni else LoadFilesFromReg; end; //------------------------------------------------------------------------------ procedure TMostRecentFiles.Notification(AComponent: TComponent; Operation: TOperation); begin inherited Notification(AComponent,Operation); if (Operation = opRemove) and (AComponent = fOwnerMenuItem) then fOwnerMenuItem := nil; end; //------------------------------------------------------------------------------ procedure TMostRecentFiles.LoadFilesFromReg; var i: cardinal; s: string; begin fFileList.Clear; with TRegistry.Create do try RootKey := HKEY_CURRENT_USER; if OpenKey(fRegPath, false) then begin for i := 1 to fMaxFiles do begin if ValueExists('MRU'+inttostr(i)) then s := readString('MRU'+inttostr(i)) else break; fFileList.Add(s); end; CloseKey; end; finally free; end; RefreshList; end; //------------------------------------------------------------------------------ procedure TMostRecentFiles.LoadFilesFromIni; var i: cardinal; LoadFrom, s: string; begin fFileList.Clear; LoadFrom := extractfilepath(fIniFilename); if LoadFrom <> '' then LoadFrom := fIniFilename else if fIniFilename = '' then LoadFrom := changefileext(paramstr(0),'.ini') //use default ini filename else LoadFrom := ExtractfilePath(Paramstr(0))+ fIniFilename; //add a path if fileExists(LoadFrom) then with TIniFile.Create(LoadFrom) do try for i := 1 to fMaxFiles do begin s := readString('MRU List',inttostr(i),''); if s = '' then break; fFileList.Add(s); end; finally free; end; RefreshList; end; //------------------------------------------------------------------------------ procedure TMostRecentFiles.SaveFilesToReg; var i: integer; begin with TRegistry.Create do try RootKey := HKEY_CURRENT_USER; if OpenKey(fRegPath, true) then begin for i := 1 to fMaxFiles do if i > fFileList.Count then writeString('MRU'+inttostr(i),'') else writeString('MRU'+inttostr(i),fFileList[i-1]); CloseKey; end; finally free; end; end; //------------------------------------------------------------------------------ procedure TMostRecentFiles.SaveFilesToIni; var i: integer; SaveTo: string; begin SaveTo := extractfilepath(fIniFilename); if SaveTo <> '' then SaveTo := fIniFilename else if fIniFilename = '' then SaveTo := changefileext(paramstr(0),'.ini') //use default ini filename else SaveTo := ExtractfilePath(Paramstr(0))+ fIniFilename; with TIniFile.Create(SaveTo) do try for i := 1 to fMaxFiles do if i > fFileList.Count then writeString('MRU List',inttostr(i),'') else writeString('MRU List',inttostr(i),fFileList[i-1]); finally free; end; end; //------------------------------------------------------------------------------ procedure TMostRecentFiles.SetRegPath(const aRegPath: string); begin fRegPath := aRegPath; //if neither designing nor loading ... if [csDesigning, csLoading] * ComponentState = [] then if fRegPath = '' then LoadFilesFromIni else LoadFilesFromReg; end; //------------------------------------------------------------------------------ procedure TMostRecentFiles.SetIniFile(const aIniFile: string); begin fIniFilename := aIniFile; //if neither designing nor loading ... if [csDesigning, csLoading] * ComponentState = [] then if fRegPath = '' then LoadFilesFromIni; end; //------------------------------------------------------------------------------ procedure TMostRecentFiles.SetOwnerMenu(aMenuItem: TMenuItem); begin fOwnerMenuItem := aMenuItem; //if neither designing nor loading ... if [csDesigning, csLoading] * ComponentState = [] then RefreshList; end; //------------------------------------------------------------------------------ procedure TMostRecentFiles.SetMaxFiles(count: cardinal); begin if count = fMaxFiles then exit; if count < 1 then fMaxFiles := 1 else if count > 8 then fMaxFiles := 8 else fMaxFiles := count; RefreshList; end; //------------------------------------------------------------------------------ procedure TMostRecentFiles.SetShowFullPath(value: boolean); begin if value = fShowFullPath then exit; fShowFullPath := value; RefreshList; end; //------------------------------------------------------------------------------ procedure TMostRecentFiles.RefreshList; var i, menuPos: integer; procedure AddMRUMenuItem(index: integer; const Caption: string); var NewItem: TMenuItem; begin NewItem := TMenuItem.Create(fOwnerMenuItem); try NewItem.Caption := Caption; NewItem.Tag := MRU_FLAG; fOwnerMenuItem.Insert(index,NewItem); if Caption <> '-' then NewItem.OnClick := DoClick; except NewItem.Free; raise; end; end; begin if (csDesigning in ComponentState) or not assigned(fOwnerMenuItem) then exit; //remove all existing MRU items ... for i := fOwnerMenuItem.Count-1 downto 0 do if fOwnerMenuItem.Items[i].Tag = MRU_FLAG then fOwnerMenuItem.Delete(i); if (fFileList.Count = 0) then exit; //that's it if (integer(fMenuPosition) >= fOwnerMenuItem.Count) then menuPos := fOwnerMenuItem.Count else menuPos := fMenuPosition; //? add a preceeding separator item... if (menuPos > 0) and (fOwnerMenuItem.Items[menuPos-1].Caption <> '-') then begin AddMRUMenuItem(MenuPos,'-'); inc(MenuPos); end; for i := 0 to fFileList.Count-1 do begin if fShowFullPath then AddMRUMenuItem(MenuPos, format('&%d %s',[i+1,fFileList[i]])) else AddMRUMenuItem(MenuPos, format('&%d %s',[i+1,extractFilename(fFileList[i])])); inc(MenuPos); end; //? add a trailing separator item... if (menuPos < fOwnerMenuItem.Count ) and (fOwnerMenuItem.Items[menuPos].Caption <> '-') then AddMRUMenuItem(MenuPos,'-'); end; //------------------------------------------------------------------------------ procedure TMostRecentFiles.DoClick(Sender: TObject); var i,idx: integer; ParentMenuItem: TMenuItem; s, filename: string; begin if not (Sender is TMenuItem) or not assigned(fMRUClickEvent) then exit; ParentMenuItem := TMenuItem(Sender).Parent; if not assigned(ParentMenuItem) then exit; //get index of Sender menuItem within Parent's menuItem list idx := ParentMenuItem.IndexOf(TMenuItem(Sender)); //find index of first item ... i := 0; while (i < ParentMenuItem.Count) and (ParentMenuItem.items[i].Tag <> MRU_FLAG) do inc(i); if (i = ParentMenuItem.Count) then exit; //should never happen if ParentMenuItem.items[i].Caption = '-' then inc(i); //skips the separator idx := idx -i; //this is the real index into fFileList if (idx < 0) or (idx >= fFileList.Count) then exit; //should never happen filename := fFileList[idx]; if not fileExists(filename) then begin //no file so warn then delete it from the list ... if assigned(fNoFileEvent) then fNoFileEvent(sender, filename) //eg: may prefer just a simple beep else begin s := format(s_no_file_exists,[filename]); if assigned(Owner) and (Owner is TCustomForm) then MessageBox(TCustomForm(Owner).handle, pchar(s),pchar(application.title), mb_iconInformation) else MessageBox(0, pchar(s),pchar(application.title), mb_iconInformation); end; fFileList.Delete(idx); RefreshList; end else begin //update order before doing something ... if idx > 0 then begin fFileList.Delete(idx); fFileList.Insert(0,Filename); RefreshList; end; if assigned(fMRUClickEvent) then fMRUClickEvent(Sender, filename); end; end; //------------------------------------------------------------------------------ function TMostRecentFiles.AddFile(const Filename: string): boolean; var i: integer; begin result := false; if not assigned(fOwnerMenuItem) then exit; i := fFileList.IndexOf(Filename); if i = 0 then exit //already the first file in list else if i > 0 then fFileList.Delete(i); fFileList.Insert(0,Filename); while fFileList.count > integer(fMaxFiles) do fFileList.delete(fMaxFiles); RefreshList; end; //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ end.