We help IT Professionals succeed at work.

How to copy folders to another location while adding the paths to a listbox?

PeterdeB
PeterdeB asked
on
Medium Priority
2,449 Views
Last Modified: 2012-06-27
Hi my friends!

Here's what I would like to do >

By a buttonclick I want to pop up the browseforfolder dialog and copy the selected folder + contents to another predefined location while adding the  path to a listbox.
My predefined location will be: D:\Data.
My listbox is empty.
I select the folder C:\Blahblah and then its contents is copied to D:\Data\Blahblah and my listbox holds one item > D:\Data\Blahblah. Adding or deleting an item from the listbox should result in adding or deleting the folder it references.

Ofcourse I could also first copy all folders to the D:\Data folder and afterwards collect the references and feed them to the listbox. What would be teh best approach?

Kind regards,

Paul

Ps working samples do the trick..

Oh btw > Afterwards I want all the references in a comma seperated list.
Comment
Watch Question

Commented:
The best approach would be to add the path everytime you do a copying. The browseforFolder dialog is unknown for me , do you mean the jedi jvBrowseForFolderDialog.
Is this what you want to achieve ?(with OpenDialog)
If OpenDialog1.Execute then
begin
   filename := OpenDialog1.FileName;
  // here the copying files part
  ListBox1.Items.Add(ExtractFileDir(filename));
end;
 

Commented:
more with this using jedi's component:

// first a procedure to copy contents of a source folder to a destination folder:
procedure CopyDir(SourceDirPath, DestDirPath: String);
var f: TSearchRec;
    IntFileAttribute: Integer;
begin
  if not (SourceDirPath[Length(SourceDirPath)] = '\')
    then SourceDirPath := SourceDirPath + '\';

  if not (DestDirPath[Length(DestDirPath)] = '\')
    then DestDirPath := DestDirPath + '\';

  FileMode:=0;
  if FindFirst(SourceDirPath + '*.*', faAnyFile, f) = 0 then
  begin
  repeat
       try
        if (f.Attr and faDirectory ) < $00000008 then
        begin
          CopyFile(PChar(SourceDirPath+f.Name),PChar (DestDirPath+f.Name),True);
          IntFileAttribute := FileGetAttr(DestDirPath + f.Name);
          FileSetAttr(DestDirPath + f.Name, IntFileAttribute);
        end;
       except
        on e: exception do
          ShowMessage(E.Message);
       end;
  until findNext(f) <> 0;
  FindClose(f);
  end;
end;


// then have a procedure that deletes the files from the used default destination folder of yours (that you could alter and put the destination folder to be variable....)

procedure DelDir(SourceDirPath: String);
var f: TSearchRec;
begin
  if not (SourceDirPath[Length(SourceDirPath)] = '\')
    then SourceDirPath := SourceDirPath + '\';

  FileMode:=0;
  if FindFirst(SourceDirPath + '*.*', faAnyFile, f) = 0 then
  begin
  repeat
       try
        if (f.Attr and faDirectory ) < $00000008 then
        begin
          DeleteFile(PChar(SourceDirPath+f.Name));
        end;
       except
        on e: exception do
          ShowMessage(E.Message);
       end;
  until findNext(f) <> 0;
  FindClose(f);
RemoveDir(SourceDirPath);
  end;
end;

//  this is not tested... but it should work. Anyway you should get the ideea afterall
// and then the events... for the button and for the ListBox:

//For the button (where Dialog1 = jvBrowseForFolderDialog)
   if Dialog1.Execute then
   begin
     If DirectoryExists('D:\Data')=false then CreateDir('D:\Data');
   CopyDir(Dialog1.Directory,'D:\Data');
   ListBox1.Items.Add(Dialog1.Directory);
   end;

// and for the onKeyUp event of the ListBox:

If Key=VK_DELETE then
begin
  ShowMessage(ListBox1.Items[ListBox1.SelCount]);
  Deldir(ListBox1.Items[ListBox1.SelCount]);
  ListBox1.DeleteSelected;
  end;
end;

This last one needs work but as I said before You should get the ideea (there's not much work to do left)
The ideea is that
1. You should make the copyfolder procedure create a text file (maybe an ini file) in the destination folder that would gather the copied filenames and assign to them the old path. Something like:
myfile.pdf - c:\FolderX\FolderY\myfile.pdf
myfile2.exe - c:\FolderX\FolderY\myfile2.exe
...

the deletefolder procedure should look inside this file and check which files corespond to the path that the item is showing.
And that would be all

Regards
Top Expert 2004

Commented:
from my paq:

u can use the shell-api,
to display the os-progress

sample

uses shellapi;

//moving file or dir with simple progress
procedure TForm1.Button1Click(Sender: TObject);
var I : Integer;
    opInfo : _SHFILEOPSTRUCT;
begin
  opInfo.pFrom := 'd:\TmpFolder';
  opInfo.pTo   := 'u:\';
  opInfo.wFunc := FO_MOVE;
  opInfo.fFlags := FOF_NOCONFIRMATION  or
                   FOF_NOCONFIRMMKDIR or
                   FOF_RENAMEONCOLLISION or
                   FOF_SIMPLEPROGRESS;
  opInfo.hNameMappings := nil;
  opInfo.fAnyOperationsAborted := False;
  opInfo.lpszProgressTitle := 'Moving . . .';
  opInfo.Wnd := self.handle;
  SHFileOperation(opInfo);
end;

//copy file or dir with simple progress
procedure TForm1.Button2Click(Sender: TObject);
var I : Integer;
    opInfo : _SHFILEOPSTRUCT;
begin
  opInfo.pFrom := 'd:\Programme\Borland\delphi5\help\del5vcl.hlp';
  opInfo.pTo   := 'u:\';
  opInfo.wFunc := FO_COPY;
  opInfo.fFlags := FOF_NOCONFIRMATION  or
                   FOF_NOCONFIRMMKDIR or
                   FOF_RENAMEONCOLLISION or
                   FOF_SIMPLEPROGRESS;
  opInfo.hNameMappings := nil;
  opInfo.fAnyOperationsAborted := False;
  opInfo.lpszProgressTitle := 'Copying . . .';
  opInfo.Wnd := self.handle;
  SHFileOperation(opInfo);
end;

meikl ;-)
Top Expert 2007

Commented:
Hi, this does everything except deleting when you click in the stringlist.
Will post that in a follow up.
Not fully tested. Take care what you click on in the browse for folder dialog. No confirmation before deleting!

Put a listbox and a button on a form:


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, FileCtrl, StdCtrls, ShellAPI;

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    function DelDir(DirName : string): Boolean;
    procedure CopyFolder(SrcFolder, ToFolder : String);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  DirSelected, NewName: string;

begin
  if SelectDirectory('Select a folder:', 'C:\', DirSelected) then begin
    NewName:='D:\Data\'+ExtractFileName(DirSelected);
    ListBox1.AddItem(NewName,nil);
    CopyFolder(DirSelected,NewName);
    DelDir(DirSelected);
  end
  else
    ShowMessage('No folder selected');
end;


function TForm1.DelDir(DirName : string): Boolean;
var
  SHFileOpStruct : TSHFileOpStruct;
  Buffer : array [0..255] of Char;
begin
  try
   Fillchar(SHFileOpStruct,Sizeof(SHFileOpStruct),0) ;
   FillChar(Buffer, Sizeof(Buffer), 0 ) ;
   StrPCopy(Buffer, DirName) ;
   with SHFileOpStruct do begin
    Wnd := 0;
    pFrom := @Buffer;
    wFunc := FO_DELETE;
    fFlags := FOF_ALLOWUNDO;
    fFlags := fFlags or FOF_NOCONFIRMATION;
    fFlags := fFlags or FOF_SILENT;
   end;
    Result := (SHFileOperation(SHFileOpStruct) = 0) ;
   except
    Result := False;
  end;
end;

procedure TForm1.CopyFolder(SrcFolder, ToFolder : String);
var
  SearchRec : TSearchRec;
  Src, Dst     : String;

begin
  Src := IncludeTrailingBackslash(SrcFolder);
  Dst := IncludeTrailingBackslash(ToFolder);
  ForceDirectories(Dst);
   if FindFirst(Src + '*', faAnyFile, SearchRec) = 0 then
    try
      repeat
        with SearchRec do
          if (Name <> '.') and (Name <> '..') then
            if (Attr and faDirectory) > 0 then
              CopyFolder(Src + Name, Dst + Name)
            else
              CopyFile(Pchar(Src + Name), PChar(Dst + Name), True);
      until FindNext(SearchRec) <> 0;
    finally
      FindClose(SearchRec);
    end ;
end;


end.
Top Expert 2007

Commented:
>except deleting when you click in the stringlist
Ok, I see calinutz's solution already provides that too...
Top Expert 2007

Commented:
Well, just for the record  ;)

procedure TForm1.ListBox1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
  var
  i:Integer;
begin
 i:=ListBox1.ItemAtPos(Point(X,Y),True);
 if i>=0 then begin
   DelDir(ListBox1.Items[i]);
   ListBox1.Items.Delete(i);
 end;
end;
Top Expert 2007

Commented:
>Adding or deleting an item from the listbox should result in adding or deleting the folder it references.

Forget my last post, it deletes the entry you click on, I somehow misunderstood it.
And I'm still not sure what this means "should result in adding or deleting the folder it references"...
Add from where? Do you add items to the listbox manually also? But maybe someone else did alredy understand your intentions better... :)

Author

Commented:
Hi TName!

The listbox should reflect the data folders content. So when I add or delete something from the listbox, the item should be removed from the data folder as well and vice versa.

Kind regards,

Paul
Top Expert 2007
Commented:
>So when I add or delete something from the listbox, the item should be removed from the data folder as well and vice versa.

I understand the delete part. What I don't quite understand is the add part.
If you add a filename/path to the listbox other than with the procedures provided  in this thread, how do you tell the listbox where the folder is originally located? (see comment in code)
The example below intercepts the add/delete messages for listbox1 to implement the changes in D:\Data ("add" not implemented for the reasons mentioned above). If you shift-click on an item, the corresponding folder will be deleted (this is just to test the delete functionality). Even if you delete a Listbox item by other means, it will try to delete the folder. Again: Test carefully!


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, FileCtrl, StdCtrls, ShellAPI;

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure ListBox1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    function DelDir(DirName : string): Boolean;
    procedure MoveDir(FromDir,ToDir:String);
    procedure CopyFolder(SrcFolder, ToFolder : String);
  public
    OldLBWndProc: TWndMethod;
    procedure LBWndProc(var Message: TMessage);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  OldLBWndProc := ListBox1.WindowProc;
  ListBox1.WindowProc := LBWndProc;
end;

procedure TForm1.LBWndProc(var Message: TMessage);
begin
  case Message.Msg of
    LB_DELETESTRING: begin
                       try
                          DelDir(ListBox1.Items[Message.WParam])
                       except
                         ShowMessage('Could not delete folder');
                       end;
                     end;
    //LB_ADDSTRING   : ShowMessage(string(Message.LParam));
    // How do you know where the folder is initially located?
    // LB_ADDSTRING   : MoveDir(?????,string(Message.LParam));
  end;
  OldLBWndProc(Message);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  DirSelected, NewName: string;
begin
  if SelectDirectory('Select a folder:', 'C:\', DirSelected) then begin
    NewName:='D:\Data\'+ExtractFileName(DirSelected);
    MoveDir(DirSelected,NewName);
  end
  else
    ShowMessage('No folder selected');
end;

procedure TForm1.MoveDir(FromDir,ToDir:String);
begin
    ListBox1.AddItem(ToDir,nil);
    CopyFolder(FromDir,ToDir);
    DelDir(FromDir);
end;

function TForm1.DelDir(DirName : string): Boolean;
var
  SHFileOpStruct : TSHFileOpStruct;
  Buffer : array [0..255] of Char;
begin
  try
   Fillchar(SHFileOpStruct,Sizeof(SHFileOpStruct),0) ;
   FillChar(Buffer, Sizeof(Buffer), 0 ) ;
   StrPCopy(Buffer, DirName) ;
   with SHFileOpStruct do begin
    Wnd := 0;
    pFrom := @Buffer;
    wFunc := FO_DELETE;
    fFlags := FOF_ALLOWUNDO;
    fFlags := fFlags or FOF_NOCONFIRMATION;
    fFlags := fFlags or FOF_SILENT;
   end;
    Result := (SHFileOperation(SHFileOpStruct) = 0) ;
   except
    Result := False;
  end;
end;

procedure TForm1.CopyFolder(SrcFolder, ToFolder : String);
var
  SearchRec : TSearchRec;
  Src, Dst     : String;

begin
  Src := IncludeTrailingBackslash(SrcFolder);
  Dst := IncludeTrailingBackslash(ToFolder);
  ForceDirectories(Dst);
   if FindFirst(Src + '*', faAnyFile, SearchRec) = 0 then
    try
      repeat
        with SearchRec do
          if (Name <> '.') and (Name <> '..') then
            if (Attr and faDirectory) > 0 then
              CopyFolder(Src + Name, Dst + Name)
            else
              CopyFile(Pchar(Src + Name), PChar(Dst + Name), True);
      until FindNext(SearchRec) <> 0;
    finally
      FindClose(SearchRec);
    end;
end;

procedure TForm1.ListBox1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
  var
  i:Integer;
begin
 i:=ListBox1.ItemAtPos(Point(X,Y),True);
 if (i>=0) and (ssCtrl in Shift) then begin
    ListBox1.Items.Delete(i);
 end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  ListBox1.WindowProc:=OldLBWndProc;
end;

end.

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts

Author

Commented:
Hi my friend!

I just noticed your tremendous reply! I tried it...it works...not sure what your question regarindg adding is about....

My kind regards,

Paul :)
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.