Solved

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

Posted on 2006-11-05
10
2,245 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.
0
Comment
Question by:PeterdeB
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 2
  • 2
  • +1
10 Comments
 
LVL 11

Expert Comment

by:calinutz
ID: 17876163
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;
 

0
 
LVL 11

Expert Comment

by:calinutz
ID: 17876216
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
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 17876242
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 ;-)
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 28

Expert Comment

by:TName
ID: 17876283
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.
0
 
LVL 28

Expert Comment

by:TName
ID: 17876302
>except deleting when you click in the stringlist
Ok, I see calinutz's solution already provides that too...
0
 
LVL 28

Expert Comment

by:TName
ID: 17876540
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;
0
 
LVL 28

Expert Comment

by:TName
ID: 17876563
>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... :)
0
 

Author Comment

by:PeterdeB
ID: 17876840
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
0
 
LVL 28

Accepted Solution

by:
TName earned 500 total points
ID: 17877306
>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.
0
 

Author Comment

by:PeterdeB
ID: 17892220
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 :)
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Come and listen to Percona CEO Peter Zaitsev discuss what’s new in Percona open source software, including Percona Server for MySQL (https://www.percona.com/software/mysql-database/percona-server) and MongoDB (https://www.percona.com/software/mongo-…
Monitoring a network: why having a policy is the best policy? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the enormous benefits of having a policy-based approach when monitoring medium and large networks. Software utilized in this v…

695 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question