一.工具界面如下(没做UI)
二.设计视图如下:
三.控件说明:
1.使用到了第三方StyleControl控件中的SCGPLabel,SCGPEdit,SCGPCheckBox,SCGPCombobox,SCGPButton,这几个控件如果需要,可替换成秕自带控件.难度-1
2.TrayIcon 这个是让程序缩小到托盘上面去的.
3.PopupMenu 菜单控件.程序缩小到托盘上时,右键可弹出菜单,如下图
4.其他控件,略
四.功能说明
1: 定时备份到指定目录
2:勾选检查MD5值时,会对最近一次备份的文件与目标文件做MD5文件比较,如果MD5值不一致,则进行备份操作.否则不备份
3.勾选开机启动可以开机自动运行
4.记忆用户设置.关闭程序时,ini文件保存到程序目录下.启动时读取此ini文件,恢复用户设置
5.点击开始后,自动缩小到托盘.托盘右键有菜单.或者双击托盘图标可显示程序界面
6.目前时间间隔只支持30分钟/1小时/3小时/6小时/12小时.暂时不支持自定义,有朋友需要的话可以二次开发,源码会在下面分享
五.源码分享
unit FMain; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, scControls, scGPControls, scGPExtControls, Vcl.StdCtrls, Vcl.Mask, Vcl.Menus, System.ImageList, Vcl.ImgList, FileCtrl, IdHashMessageDigest, IOUtils, IdHash, DateUtils, System.Types, Registry, IniFiles, IdGlobal; type TMD5 = class(TIdHashMessageDigest5); //注意这里 TForm2 = class(TForm) scGPEdit1: TscGPEdit; scGPLabel1: TscGPLabel; scGPLabel2: TscGPLabel; scGPComboBox1: TscGPComboBox; BeginButton: TscGPButton; OpenDialog1: TOpenDialog; Timer1: TTimer; scGPEdit2: TscGPEdit; scGPLabel3: TscGPLabel; scGPCheckBox1: TscGPCheckBox; TrayIcon1: TTrayIcon; PopupMenu1: TPopupMenu; N1: TMenuItem; N2: TMenuItem; N3: TMenuItem; ImageList1: TImageList; scGPCheckBox2: TscGPCheckBox; procedure scGPEdit2RightButtonClick(Sender: TObject); procedure scGPEdit1RightButtonClick(Sender: TObject); procedure BeginButtonClick(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure N2Click(Sender: TObject); procedure N3Click(Sender: TObject); procedure N1Click(Sender: TObject); procedure scGPCheckBox2Click(Sender: TObject); procedure TrayIcon1DblClick(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } procedure AppendRecordToFile(RecordContent: string); procedure SetStartupRegistry(EnableStartup: Boolean); procedure SaveSettings(const FileName: string; FilePath, FolderPath: string); procedure LoadSettings(const FileName: string; var FilePath, FolderPath: string); function GetLatestFileMD5(const filePath, folderPath: string): string; function StreamToMD5(const FilePatn: string): string; end; var Form2: TForm2; filePath: string; //文件路径 FolderPath: string; //备份目录 implementation {$R *.dfm} procedure TForm2.BeginButtonClick(Sender: TObject); var i: Cardinal; begin if BeginButton.Caption = '停止' then begin AppendRecordToFile(FormatDateTime('yyyymmdd hhmmss', Now()) + ' 任务被停止'); BeginButton.Caption := '开始'; Timer1.Enabled := false; end else begin //检查是否已指定文件与保存目录 filePath := scGPEdit1.Text; FolderPath := scGPEdit2.Text; if (filePath = '') or (FolderPath = '') then begin ShowMessage('请先选择要备份的文件与存放备份文件的目录'); exit; end; //如果文件名不存在,则提示文件名不存在,然后退出程序 if not FileExists(filePath) then begin ShowMessage('指定的 文件 不存在,请检查'); exit; end; //检查目录是否存在 if not DirectoryExists(FolderPath) then begin ShowMessage('指定的 文件夹路径 不存在,请检查'); exit; end; BeginButton.Caption := '停止'; case scGPComboBox1.ItemIndex of 0: i := 30 * 60 * 1000; 1: i := 60 * 60 * 1000; 2: i := 3 * 60 * 60 * 1000; 3: i := 6 * 60 * 60 * 1000; 4: i := 12 * 60 * 60 * 1000; end; AppendRecordToFile(FormatDateTime('yyyy-mm-dd hh:mm:ss', Now()) + ' 开始执行备份任务;'); Timer1.Interval := i; //设置时间间隔 ,测试时写个几秒即可 Timer1.Enabled := True; //启动计时器 //隐藏到托盘 TrayIcon1.Visible := True; // 显示托盘图标 TrayIcon1.PopUpMenu := PopupMenu1; // 将弹出菜单关联到托盘图标上 Self.Hide; end; end; procedure TForm2.scGPCheckBox2Click(Sender: TObject); //选择备份目录 begin if scGPCheckBox2.STATE = cbChecked then SetStartupRegistry(TRUE) //设置开机启动 else SetStartupRegistry(false) //取消开机启动 end; procedure TForm2.scGPEdit1RightButtonClick(Sender: TObject); begin OpenDialog1.Options := [ofHideReadOnly, ofFileMustExist]; //对话框设置:隐藏只读文件,文件必须存在.不需要的可以注释掉 if OpenDialog1.Execute then scGPEdit1.Text := OpenDialog1.FileName; //返回用户选中的文件路径到文本框 end; procedure TForm2.scGPEdit2RightButtonClick(Sender: TObject); var Dir: string; begin if SelectDirectory('请选择目录 ', ' ', Dir) then // Dir存储着用户选择的目录名称 scGPEdit2.Text := Dir; //返回用户选中的文件夹路径到文本框 end; procedure TForm2.Timer1Timer(Sender: TObject); //计时器 var NewMD5, OldMD5: string; FileStream: TFileStream; MD5Hash: TIdHashMessageDigest5; logStr: string; begin logStr := FormatDateTime('yyyymmdd hhmmss', Now()); if scGPCheckBox1.State = cbChecked then //如果勾选了检查MD5值 begin //取到目标文件的MD5值 FileStream := TFileStream.Create(FilePath, fmOpenRead or fmShareDenyNone); try MD5Hash := TIdHashMessageDigest5.Create; try NewMD5 := MD5Hash.HashStreamAsHex(FileStream); finally MD5Hash.Free; end; finally FileStream.Free; end; AppendRecordToFile('目标文件MD5值:' + NewMD5); //输出日志到备份日志 //获取到最近备份文件的MD5值 . OldMD5 := GetLatestFileMD5(FilePath, FolderPath); AppendRecordToFile('最新文件MD5值:' + OldMD5); //如果OldMD5的值等于NewMD5值,说明数据库没有变化,不需要进行备份 if NewMD5 = OldMD5 then begin AppendRecordToFile(logStr + 'MD5值未发生改变,不进行备份操作'); exit; end else AppendRecordToFile(logStr + 'MD5值有变动,进行备份操作'); end; //开始备份 //TPath.Combine 方法来组合目标目录 FolderPath 和新的文件名。这样可以确保目标文件的完整路径,它会自动加"\"。 //使用 TPath.GetExtension 方法获取源文件的扩展名,并将其与新的文件名进行组合。 TFile.Copy(filePath, TPath.Combine(FolderPath, logStr + TPath.GetExtension (filePath))); AppendRecordToFile(logStr + ' 备份完成'); end; procedure TForm2.TrayIcon1DblClick(Sender: TObject); //双击时显示界面 begin self.Show; end; procedure TForm2.AppendRecordToFile(RecordContent: string); //追加文本信息到日志文件 var FullPath: string; FileWriter: TStreamWriter; begin FullPath := TPath.Combine(FolderPath, '备份日志.txt'); FileWriter := TStreamWriter.Create(FullPath, FileExists(FullPath)); try FileWriter.WriteLine(RecordContent); finally FileWriter.Free; end; end; function TForm2.GetLatestFileMD5(const filePath, folderPath: string): string; //找到最近备份文件,并返回MD5 var FileType: string; SearchRec: TSearchRec; CreateTime, LatestCreateTime: TDateTime; FullPath, LatestFilePath: string; begin Result := ''; FileType := '*' + TPath.GetExtension(filePath); // 获取文件扩展名,与*构成模糊匹配 FullPath := TPath.Combine(folderPath, FileType); //带路径的文件名 //第一个文件,默认它是最新的文件,然后再慢慢遍历 if FindFirst(FullPath, faAnyFile, SearchRec) = 0 then begin FullPath := TPath.Combine(folderPath, SearchRec.Name); LatestCreateTime := Tfile.GetCreationTime(FullPath); //文件的创建时间 LatestFilePath := FullPath; //文件路径 // 遍历文件夹中的文件 while FindNext(SearchRec) = 0 do begin // 比较文件的创建时间,并更新最新文件的信息 FullPath := TPath.Combine(folderPath, SearchRec.Name); CreateTime := Tfile.GetCreationTime(FullPath); //文件的创建时间 if CreateTime > LatestCreateTime then //比较两个文件的创建时间 begin LatestFilePath := FullPath; //记录更近的备份文件的文件名 LatestCreateTime := CreateTime; // 记录更近的备份文件的创建时间 end; end; // 将最新文件的路径传递给 StreamToMD5() 函数来计算 MD5 Result := StreamToMD5(LatestFilePath); end; FindClose(SearchRec); //关闭记录类型 end; procedure TForm2.N1Click(Sender: TObject); //显示 菜单 begin Self.Show; end; procedure TForm2.N2Click(Sender: TObject); //关于 菜单 begin ShowMessage('制作人:甘兴鹏 QQ:452428745') end; procedure TForm2.N3Click(Sender: TObject); //退出 菜单 begin TrayIcon1.Visible := False; //关闭前,设置托盘不可见,不然退出了还会有个图标显示在那里 Close; end; procedure TForm2.SetStartupRegistry(EnableStartup: Boolean); //设置开机启动 var Reg: TRegistry; begin //ExtractFileName(ParamStr(0)) 来获取当前程序的文件名作为注册表键名和值。 //ParamStr(0) 返回当前程序的完整路径 //ExtractFileName 函数提取出程序的文件名部分。 Reg := TRegistry.Create; try Reg.RootKey := HKEY_CURRENT_USER; if Reg.OpenKey('Software\Microsoft\Windows\CurrentVersion\Run', True) then //仅于WIN10测试 begin if EnableStartup then Reg.WriteString(ExtractFileName(ParamStr(0)), ParamStr(0)) // 将程序路径设置为开机启动项的值,键名为程序名称 else Reg.DeleteValue(ExtractFileName(ParamStr(0))); // 删除开机启动项的值,键名为程序名称 Reg.CloseKey; end; finally Reg.Free; end; end; // 保存设置到配置文件 procedure TForm2.SaveSettings(const FileName: string; FilePath, FolderPath: string); var IniFile: TIniFile; begin IniFile := TIniFile.Create(FileName); try IniFile.WriteString('Settings', 'FilePath', scGPEdit1.Text); IniFile.WriteString('Settings', 'FolderPath', scGPEdit2.Text); finally IniFile.Free; end; end; // 从配置文件中读取设置 procedure TForm2.LoadSettings(const FileName: string; var FilePath, FolderPath: string); var IniFile: TIniFile; begin IniFile := TIniFile.Create(FileName); try scGPEdit1.Text := IniFile.ReadString('Settings', 'FilePath', ''); scGPEdit2.Text := IniFile.ReadString('Settings', 'FolderPath', ''); finally IniFile.Free; end; end; // 在程序启动时自动读取设置 procedure TForm2.FormCreate(Sender: TObject); var AppPath: string; ConfigFile: string; FilePath, FolderPath: string; begin AppPath := ExtractFilePath(Application.ExeName); ConfigFile := AppPath + 'config.ini'; FilePath := scGPEdit1.Text; FolderPath := scgpEdit2.Text; if FileExists(ConfigFile) then LoadSettings(ConfigFile, FilePath, FolderPath); end; // 在程序关闭时保存设置 procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction); var AppPath: string; ConfigFile: string; begin AppPath := ExtractFilePath(Application.ExeName); ConfigFile := AppPath + 'config.ini'; SaveSettings(ConfigFile, scGPEdit1.Text, scgpEdit2.Text); end; function TForm2.StreamToMD5(const FilePatn: string): string; //取文件的MD5值 var MD5Encode: TMD5; filesen: TFileStream; begin MD5Encode := TMD5.Create; try filesen := TFileStream.Create(FilePatn, fmopenread or fmshareExclusive); result := MD5Encode.HashStreamAsHex(filesen); finally MD5Encode.Free; filesen.Free end; end; end.
标签:begin,end,string,DELPHI,TObject,源码,备份,procedure,Sender From: https://www.cnblogs.com/yoooos/p/17643011.html