Kopiowanie katalogu z progressem lub gauge kopia bazy danych

0

Witam wielmożnych guru w temacie,
w poniższym kodzie mam kopiowanie plików z jednego katalogu do drugiego. Niestety nie pokazuje ono przebiegu kopiowania. Mam pytanko jak do tego zrobić żeby pokazywało przebieg kopiowania progressbar lub guage oraz dawało wybór miejsca gdzie mają być umieszczone dane. dobrą funkcja było by odtworzenie też danych z katalogu kopia do katalogu dane.
W taki sposób powstanie cos w rodzaju tworzenia kopii danych.

Z góry dziękuję za zainteresowanie.
wiem że przykład jest troszkę długi ale prosze o pomoc, bo stoję z tym i nie moge ruszyć. Aha pisze w Delphi 5.

procedure TForm2.Button5Click(Sender: TObject);

var FOS:TSHFileOpStructA;
begin
with FOS do
begin
Wnd:=Handle;
wFunc:=FO_COPY;
pFrom:='c:\program\Dane*.*';
pTo:='c:\program\kopia';
fFlags:=FOF_ALLOWUNDO or FOF_NOCONFIRMMKDIR;
lpszProgressTitle:='Kopiowanie...';
fAnyOperationsAborted:=False;
end;
if SHFileOperation(FOS)<>0 then
ShowMessage('Wystąpił błąd podczas kopiowania')
else
if FOS.fAnyOperationsAborted then
ShowMessage('Kopiowanie zostało przerwane');
end;

Z góry dziękuję za zainteresowanie.
Serdecznie pozdrawiam
waldi

0

Czesc, mozesz zrealizowac progress bar na dwa sposoby(ktore w tym momencie mi przyszly do glowy) w zaleznosci od tego jak dokladny progress bar to ma byc.

Sposob 1 (dokladnosc do pliku):

Na poczatku musisz zliczyc ilosc plikow w katalogu zrodlowym, oraz pobrac sobie wszystkie sciezki do tych plikow. Oczywiscie ilosc plikow to Twoj TProgressBar.Max. Nastepnie dla kazdego pliku, ktorego masz sciezke, w petli wypelniasz sobie ta strukturke, ktora nam przedstawiles i wywolujesz ta funkcje WinAPI. Zmieniasz tylko pFrom na pojedyncze sciezki plikow. W petli zmieniasz TProgressBar.Position oraz wywolujesz Application.ProcessMessages. No i masz progress bara z dokladnoscia do pliku.

Sposob 2 (dokladnosc do bajtu):

Tak jak wczesniej, pobierasz sciezki do wszystkich plikow i zliczasz wielkosc kazdego pliku. Sumaryczna wielkosc wszystkich plikow = TProgressBar.Max. Reszte wykonujesz tak samo z tym ze inkrementujesz TProgressBar.Position o wielkosc ostatnio skopiowanego pliku. Proste ? ;)

Jakby co daj znac.

0

Witam,
Mam 4 pliki w tym katalogu Dane:
nazwiska.dbf, nazwiska.mdx, nazwiska.dbt i numer.dbf
Nie jestem dobry w te klocki i proszę o pomoc może coś w rodzaju gotowca do w/w przykładu.

Serdecznie pozdrawiam i proszę o wyrozumiałość
waldi

0

Witaj.

Formatowanie kodu nie zaszkodzi ;)

Wrzuc wrapper na ta funkcje Api(i na strukture, ktora jej podajesz) z ktorej korzystasz to cos poradzimy ;)

Naprawde, nie chce mi sie tego robic samemu. Jak chcesz gotowca, moglbys sie troche bardziej postarac ;)

0

Witam serdecznie,
mam pytanko ?

Wodzu napisał(a)

Witaj.

Formatowanie kodu nie zaszkodzi ;)

Wrzuc wrapper na ta funkcje Api(i na strukture, ktora jej podajesz) z ktorej korzystasz to cos poradzimy ;)

Naprawde, nie chce mi sie tego robic samemu. Jak chcesz gotowca, moglbys sie troche bardziej postarac ;)

a jak bardzo Ci nie chce się tego gotowca napisać ?
Prosze ...
Serdecznie pozdrawiam i dziękuję za zainteresowanie.
waldi

0

Moze zle sie wyrazilem ;)

Poprosze o przyklad kompilowalny i dzialajacy Twojego obecnego kopiowania...

0

Witam,
tu jest cały pas który tworzy tą całą procedurę kopiowania danych z jednego katalogu do katalogu i z powrotem.
Jest to jedna część z programu. Reszta programu to wprowadzanie danych i ich przeglądanie. Dlatego mam tu Form3

unit Unit3;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ShellApi,
StdCtrls, Gauges, ComCtrls;

type
TForm3 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Gauge1: TGauge;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure FormCreate(Sender: TObject);

private
{ Private declarations }
public
{ Public declarations }
end;

var
Form3: TForm3;

implementation

{$R *.DFM}

procedure TForm3.Button1Click(Sender: TObject); //tworzenie danych
var FOS:TSHFileOpStructA;
begin
with FOS do
begin
Wnd:=Handle;
wFunc:=FO_COPY;
pFrom:='c:\aprogram\Dane*.*';
pTo:='c:\aprogram\kopia';
fFlags:=FOF_ALLOWUNDO or FOF_NOCONFIRMMKDIR;
lpszProgressTitle:='Kopiowanie danych...';
fAnyOperationsAborted:=False;
end;
if SHFileOperation(FOS)<>0 then
ShowMessage('Wystąpił błąd podczas kopiowania')
else
if FOS.fAnyOperationsAborted then
ShowMessage('Kopiowanie zostało przerwane');

Application.MessageBox('Kopiowanie zakończono',
'Informacja', MB_ApplModal+MB_ICONINFORMATION or MB_OK);
end;

procedure TForm3.FormCreate(Sender: TObject);
begin
Sleep(5000); // 5 sek 5000
Application.ProcessMessages; // nie blokuje działania programu
Gauge1.Progress:=100;
end;

procedure TForm3.Button2Click(Sender: TObject); //odtwarzanie danych
var FOS:TSHFileOpStructA;
begin
with FOS do
begin
Wnd:=Handle;
wFunc:=FO_COPY;
pFrom:='c:\aprogram\kopia*.*';
pTo:='c:\aprogram\Dane';
fFlags:=FOF_ALLOWUNDO or FOF_NOCONFIRMMKDIR;
lpszProgressTitle:='Kopiowanie danych...';
fAnyOperationsAborted:=False;
end;
if SHFileOperation(FOS)<>0 then
ShowMessage('Wystąpił błąd podczas kopiowania')
else
if FOS.fAnyOperationsAborted then
ShowMessage('Kopiowanie zostało przerwane');
Application.MessageBox('Zakończono odtwarzanie danych',
'Informacja', MB_ApplModal+MB_ICONINFORMATION or MB_OK);
end;

procedure TForm3.Button3Click(Sender: TObject);

var
numBtn: Integer;
begin
numBtn:= Application.MessageBox('na pewno Kończysz ?',
'Zakończenie pracy w formularzu',
MB_ICONQUESTION or MB_YESNO);
if (numBtn = IDYES) then
begin
ShowMessage('Hey to wychodzimy z tworznia kopii danych');
close
end;

end;
end.

Serdecznie pozdrawiam
Waldi

0

Czesc.

Juz zaczalem Ci pisac tego progress bara jednak stwierdzilem, ze poczytam jeszcze troche o tym:

TSHFileOpStructA

okazuje sie, ze wystarczy dodac do tej strukturki flage FOF_SIMPLEPROGRESS i bedziesz mial windowsowego progress bara. Czy tak moze byc?

Pozdrawiam.

0

Witam Wielmożnych Guru,
dopisałem do każdej procedury kopiowania tutaj:
fFlags:=FOF_ALLOWUNDO or FOF_NOCONFIRMMKDIR;
ten Twój FOF_SIMPLEPROGRESS
teraz mam taki kod:
fFlags:=FOF_ALLOWUNDO or FOF_NOCONFIRMMKDIR or FOF_SIMPLEPROGRESS;
musiałem dopisać OR ponieważ wyrzucał mi błędy:

[Error] Unit3.pas(42): Missing operator or semicolon.
[Error] Unit3.pas(42): Statement expected, but expression of type 'Integer' found.
[Error] Unit3.pas(66): Missing operator or semicolon
[Error] Unit3.pas(66): Statement expected, but expression of type 'Integer' found
[Fatal Error] Adreska.dpr(9): Could not compile used unit 'Unit3.pas'
Nie wiem czy dobrze zrobiłem dopisując te or
Efekt jest taki że pokazuje mi kopiowanie tak jak jest w windows "żółte koperty". Na szybkim komputerze nie ma tego widocznego efektu. Gdyby coś takiego zrobić żeby użytkownik widział postęp np. w procentach Tgauge lub jakoś inaczej. Chodzi o to żeby był widoczny postęp kopiownia.
Serdecznie pozdrawiam i dziękuję za wyrozumiałość
Waldi

0

Czesc.

Twoj upor w dazeniu do celu zostal nagrodzony ;P Zrobie Ci gotowca jednakze chcialbym Ci takze pokazac jak winien przebiegac Twoj proces myslowy, moze to Ci ulatwi pisanie kodu w przyszlosci...

Wodzu napisał(a)

Sposob 2 (dokladnosc do bajtu):

Tak jak wczesniej, pobierasz sciezki do wszystkich plikow i zliczasz wielkosc kazdego pliku. Sumaryczna wielkosc wszystkich plikow = TProgressBar.Max. Reszte wykonujesz tak samo z tym ze inkrementujesz TProgressBar.Position o wielkosc ostatnio skopiowanego pliku. Proste ? ;)

Tutaj masz wszystko co potrzeba aby sobie zaimplementowac ten postep.

Wodzu napisał(a)

...zliczasz wielkosc kazdego pliku

Musimy znalezc metode na znalezienie wielkosci danego pliku. Moze cos z "file" i "size" bedzie w helpie Delphi? No patrz! Jest:

FileSize - Returns the current size of a file; not used for text files.

W dodatku Delphi 7 prawie od razu daje nam przyklad na kopiowanie pliku. To chyba nasz szczesliwy dzien ;).

var
  FromF, ToF: file;
  NumRead, NumWritten: Integer;
  Buf: array[1..2048] of Char;
begin
  if OpenDialog1.Execute then     { Display Open dialog box }
  begin
    AssignFile(FromF, OpenDialog1.FileName);
    Reset(FromF, 1);    { Record size = 1 }
    if SaveDialog1.Execute then      { Display Save dialog box}
    begin
      AssignFile(ToF, SaveDialog1.FileName);    { Open output file }
      Rewrite(ToF, 1);  { Record size = 1 }
      repeat
        BlockRead(FromF, Buf, SizeOf(Buf), NumRead);
        BlockWrite(ToF, Buf, NumRead, NumWritten);
      until (NumRead = 0) or (NumWritten <> NumRead);
      CloseFile(FromF);
      CloseFile(ToF);
    end;
  end;

Wystarczy do tego dodac dwie linie kodu aby miec postep kopiowania pliku. Ale pierwej przerobmy to na procedurke i ogarnijmy troche kod.

procedure CopyFileWithProgress(const AFrom, ATo: String; var AProgress: TProgressBar);
var
  FromF, ToF: file;
  NumRead, NumWritten, DataSize: Integer;
  Buf: array[1..2048] of Char;
begin
  DataSize := SizeOf(Buf);
  AssignFile(FromF, AFrom);
  Reset(FromF, 1);
  AssignFile(ToF, ATo);
  Rewrite(ToF, 1);
  repeat
    BlockRead(FromF, Buf, DataSize, NumRead);
    BlockWrite(ToF, Buf, NumRead, NumWritten);
    AProgress.Position := AProgress.Position + DataSize;
    Application.ProcessMessages;
  until (NumRead = 0) or (NumWritten <> NumRead);
  CloseFile(FromF);
  CloseFile(ToF);
end;

Jako parametr przekazujemy oprocz sciezek do plikow rowniez TProgressBar gdyz musimy zmieniac jego pozycje.

Mamy wiec kopiowanie jednego pliku z postepem operacji (gdy znamy wczesniej rozmiar tego pliku).

Teraz pora na skorzystanie z kolejnej wskazowki:

Wodzu napisał(a)

pobierasz sciezki do wszystkich plikow

Czesto walkowany temat na forum ale jak gotowiec to gotowiec ;) Pozwolilem sobie napisac funkcje przeszukujaca rekurencyjnie dany katalog i znajdujaca pliki do kopiowania. Wyglada ona tak:

procedure GatherFilesFromDirectory(const ADirectory: String;
  var AFileList: TStringList; var ATotalSize: Int64);
var
  SR: TSearchRec;
begin
  if FindFirst(ADirectory + '\*.*', faDirectory, sr) = 0 then
  begin
    repeat
      if ((SR.Attr and faDirectory) = SR.Attr) and (SR.Name <> '.') and (SR.Name <> '..') then
        GatherFilesFromDirectory(ADirectory + '\' + Sr.Name, AFileList, ATotalSize);
    until FindNext(SR) <> 0;
    FindClose(SR);
  end;

  if FindFirst(ADirectory + '\*.*', 0, SR) = 0 then
  begin
    repeat
      AFileList.Add(ADirectory + '\' + SR.Name);
      Inc(ATotalSize, SR.Size);
    until FindNext(SR) <> 0;
    FindClose(SR);
  end;
end;

ADirectory to folder startowy. AFileList to wskaznik na TStringList w ktorej trzymamy znalezione sciezki do plikow. Dodatkowo w ATotalSize mamy wielkosc w bajtach wszystkich znalezionych plikow, potrzebne do TProgressBar.Max.

No i w sumie gotowe. Mozna z tego skorzystac np tak:


procedure TfmMain.btCopyClick(Sender: TObject);
var
  FileList: TStringList;
  TotalSize: Int64;
  i: Integer;
begin
  TotalSize := 0;
  FileList := TStringList.Create;
  GatherFilesFromDirectory(edCopyFrom.Text, FileList, TotalSize);
  pbProgress.Position := 0;
  pbProgress.Max := TotalSize;
  for i := 0 to FileList.Count - 1 do
  begin
    lbFile.Caption := 'Plik ' + FileList[i];
    CopyFileWithProgress(FileList[i], edCopyTo.Text + ExtractFileName(FileList[i]), pbProgress);
  end;
  FileList.Free;
end;

Dodatkowo bedzie pokazywalo nazwe aktualnie kopiowanego pliku.

Pod tym linkiem znajdziesz program ze zrodlami:

http://www.speedyshare.com/527574196.html

Pozdrawiam

PS. Polecam ProgressBary z pakietu komponentow JEDI.

1 użytkowników online, w tym zalogowanych: 0, gości: 1