Solved

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

Posted on 2006-11-05
10
2,207 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
  • 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
 
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
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
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

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
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…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

705 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

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now