Mega Code Archive

 
Categories / Delphi / System
 

Home made RecycleBin

Title: Home made RecycleBin Question: How to restore files from the recycle bin and delete files present in the recycle bin. Answer: To restore as well as delete file from the bin you need to make use of the following functions. function SHQueryRecycleBin(pszrtootpath:pchar;QUERYRBINFO:pshqueryrbinfo):integer;stdcall;external 'shell32' name 'SHQueryRecycleBinA'; //used to get the number of files in the bin. function _FindFirstChangeNotification(lpPathName: PChar;bWatchSubtree:TWinBool;dwNotifyFilter: DWORD): THandle;stdcall; external kernel32 name 'FindFirstChangeNotificationA'; // used to notify the program when user has deleted a file function SHEmptyRecycleBin(hwnd:thandle;pszRootPath:pchar;dwFlags:integer):integer;stdcall;external 'shell32.dll' name'SHEmptyRecycleBinA'; //This function empties the recycle bin. In delphi the function FindFirstChangeNotification is already declared but in Delphi 3 and above it does not work correctly.If the second parameter is true then the function always returns an invalid handle.(visit http://members.aye.net/~bstowers/delphi/bugs/ for more info). So you need to redeclare the FindFirstChangeNotification function as shown below. type TWinBool = (winFalse, winTrue); function _FindFirstChangeNotification(lpPathName: PChar;bWatchSubtree:TWinBool;dwNotifyFilter: DWORD): THandle;stdcall; external kernel32 name 'FindFirstChangeNotificationA'; The above function is used to refresh the list of files in the recyclebin when the user deletes a file. To use this function we have to first create a thread.This thread checks continuosly checks whether any file was deleted and then refreshes the list of deleted items. For more information see delphi tips 'SHQUERYBINFO', 'SHemptyrecycleBin', 'Get the list of files from bin'. Here is the code of the thread. unit Unit2; interface uses Classes,SysUtils,windows; type TFileChangeNotify = class(TThread) private protected procedure Execute; override; procedure filenotify;//refreshes the list when user has deleted a file. end; var qh1:thandle; implementation uses unit1; procedure TFileChangeNotify.filenotify; begin form1.refreshlist; end; procedure TFileChangeNotify.Execute; var pdir:pchar; st:integer; tmp:boolean; begin pdir:='C:\'; qh1:=0; qh1:=_FindFirstChangeNotification(pdir,Twinbool(1),FILE_NOTIFY_CHANGE_LAST_WRITE); while true do begin st:=WaitForSingleObject(qh1,INFINITE); if st=WAIT_OBJECT_0 then begin Synchronize(filenotify); SHUpdateRecycleBinIcon; end; tmp:=findnextchangenotification(qh1); if tmp=false then Terminate; end; end; end. You need to add a Tlistview control to your form, and add two columns to it. Here is the code of main program. unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Menus, ComCtrls,unit2;{unit2 is the unit in which the thread resides} const SHERB_NOCONFIRMATION = $1; const SHERB_NOPROGRESSUI = $2; const SHERB_NOSOUND = $4; type TWinBool = (winFalse, winTrue); type Tfbuf=packed record data:array[0..255]of char; u1:array[0..3] of char; recno:smallint; u2:array[0..18] of char; end; type SHQUERYRBINFO =packed record cbSize:integer; i64Size:int64; i64NumItems:int64; end; pshqueryrbinfo =^SHQUERYRBINFO; function SHQueryRecycleBin(pszrtootpath:pchar;QUERYRBINFO:pshqueryrbinfo):integer;stdcall;external 'shell32' name 'SHQueryRecycleBinA'; function _FindFirstChangeNotification(lpPathName: PChar;bWatchSubtree:TWinBool;dwNotifyFilter: DWORD): THandle;stdcall; external kernel32 name 'FindFirstChangeNotificationA'; function SHUpdateRecycleBinIcon:integer;stdcall;external 'shell32.dll'; function SHEmptyRecycleBin(hwnd:thandle;pszRootPath:pchar;dwFlags:integer):integer;stdcall;external 'shell32.dll' name'SHEmptyRecycleBinA'; type TForm1 = class(TForm) RBinList: TListView; MainMenu1: TMainMenu; file1: TMenuItem; View1: TMenuItem; Refresh1: TMenuItem; Edit1: TMenuItem; SelectAll1: TMenuItem; Restore1: TMenuItem; N1: TMenuItem; Delete1: TMenuItem; N2: TMenuItem; Close1: TMenuItem; InvertSelection1: TMenuItem; procedure FormCreate(Sender: TObject); procedure Refresh1Click(Sender: TObject); procedure FormResize(Sender: TObject); procedure file1Click(Sender: TObject); procedure SelectAll1Click(Sender: TObject); procedure InvertSelection1Click(Sender: TObject); procedure Restore1Click(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure Close1Click(Sender: TObject); procedure FormShow(Sender: TObject); procedure Delete1Click(Sender: TObject); private { Private declarations } public qh:thandle; procedure refreshlist; function updateinfo(fname:string):boolean;//Makes appropriate changes to the INFO2 file //present in recycled folder. procedure Restorefiles;//restores the selected files from the recycle bin. procedure deletefiles;//deletes the selected files from the recycle bin. end; var Form1: TForm1; rbinfo:SHQUERYRBINFO; reccount:integer; fhandle:integer; monitorthread:TFileChangeNotify; implementation {$R *.DFM} procedure tform1.deletefiles; var i:integer; sname:string; dname:string; begin monitorthread.Suspend; for i:=0 to rbinlist.Items.Count-1 do begin if rbinlist.Items[i].Selected=true then begin sname:=ExtractFileDrive(rbinlist.Items[i].SubItems[0]) + '\Recycled\DC'+rbinlist.Items[i].SubItems[1]+ExtractFileExt(rbinlist.Items[i].caption); dname:=rbinlist.Items[i].SubItems[0]+rbinlist.Items[i].caption; deleteFile(sname); updateinfo(dname); end; end; monitorthread.Resume; end; function tform1.updateinfo(fname:string):boolean; var rbuff:Tfbuf; fread:integer; tsize:integer; aname:pchar; ch: char; begin result:=false; ch:=#0; fhandle:=fileopen('C:\recycled\info2',fmOpenReadWrite or fmShareDenyNone); if fhandle0 then begin tsize:=GetFileSize(fhandle,nil); setfilepointer(fhandle,20,nil,FILE_BEGIN); fread:=20; while(fread begin fread:=fread+fileread(fhandle,rbuff,280); if rbuff.data[0]#0 then begin aname:=pchar(@rbuff.data[0]); if StrComp(aname,pchar(fname))=0 then begin setfilepointer(fhandle,-280,nil,FILE_CURRENT); filewrite(fhandle,ch,1); result:=true; break; end; end; end; fileclose(fhandle); end; end; procedure tform1.refreshlist; var rbuff:Tfbuf; fread:integer; tsize:integer; aname:pchar; fitem:tlistitem; dname:pchar; iconhandle:thandle; tmp:word; iconid:integer; icon:ticon; begin monitorthread.Suspend; zeromemory(@rbuff,sizeof(rbuff)); rbinlist.Items.Clear; fhandle:=fileopen('C:\recycled\info2',fmOpenRead); if fhandle0 then begin tsize:=GetFileSize(fhandle,nil); setfilepointer(fhandle,20,nil,FILE_BEGIN); fread:=20; while(fread begin fread:=fread+fileread(fhandle,rbuff,280); if rbuff.data[0]#0 then begin aname:=pchar(@rbuff.data[0]); dname:=pchar((ExtractFileDrive(aname)+'\Recycled\DC'+inttostr (rbuff.recno)+extractfileext(aname))); iconhandle:=ExtractAssociatedIcon(HInstance,dname,tmp); icon.Handle:=iconhandle; iconid:=largeimagelist.AddIcon(icon); fitem:=rbinlist.Items.add; fitem.ImageIndex:=iconid; fitem.Caption:=ExtractFileName(aname); fitem.SubItems.Add(ExtractFilePath(aname)); fitem.SubItems.add(inttostr(rbuff.recno)); end; end; fileclose(fhandle); end; rbinfo.cbSize:=sizeof(rbinfo); rbinfo.i64NumItems:=0; rbinfo.i64Size:=0; SHQueryRecycleBin('C:\',@rbinfo); if (rbinlist.items.count=0) and (rbinfo.i64Size0) then SHEmptyRecycleBin(form1.handle,'C:\',SHERB_NOCONFIRMATION or SHERB_NOPROGRESSUI); monitorthread.resume; end; procedure TForm1.FormCreate(Sender: TObject); begin monitorthread:=TFileChangeNotify.Create(false); end; procedure TForm1.Refresh1Click(Sender: TObject); begin refreshlist; end; procedure TForm1.FormResize(Sender: TObject); begin rbinlist.width:=form1.width-8; rbinlist.height:=form1.height-48; end; procedure TForm1.file1Click(Sender: TObject); begin if rbinlist.SelCount0 then begin restore1.enabled:=true; Delete1.enabled:=true; end else begin restore1.enabled:=false; Delete1.enabled:=false; end; end; procedure TForm1.SelectAll1Click(Sender: TObject); var i:integer; begin for i:= 0 to rbinlist.Items.Count-1 do rbinlist.Items[i].Selected:=true; end; procedure TForm1.InvertSelection1Click(Sender: TObject); var i:integer; begin for i:= 0 to rbinlist.Items.Count-1 do rbinlist.Items[i].Selected:=not(rbinlist.Items[i].Selected); end; procedure tform1.Restorefiles; var i:integer; sname:string; dname:string; begin monitorthread.Suspend; for i:=0 to rbinlist.Items.Count-1 do begin if rbinlist.Items[i].Selected=true then begin sname:=ExtractFileDrive(rbinlist.Items[i].SubItems[0]) + '\Recycled\DC'+rbinlist.Items[i].SubItems[1]+ExtractFileExt(rbinlist.Items[i].caption); dname:=rbinlist.Items[i].SubItems[0]+rbinlist.Items[i].caption; MoveFile(pchar(sname),pchar(dname)); updateinfo(dname); end; end; monitorthread.Resume; end; procedure TForm1.Restore1Click(Sender: TObject); begin restorefiles; end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin if qhINVALID_HANDLE_VALUE then FindCloseChangeNotification(qh); monitorthread.Terminate; end; procedure TForm1.Close1Click(Sender: TObject); begin form1.close; end; procedure TForm1.FormShow(Sender: TObject); begin refreshlist; end; procedure TForm1.Delete1Click(Sender: TObject); begin deletefiles; end; end.