Seite 2 von 3

Re: ListViewGadget leeren und neu befüllen

Verfasst: 14.04.2010 14:32
von ts-soft
Im timerereignis rufste folgende Procedure auf:

Code: Alles auswählen

Global NewList tocopy.s()

Procedure Kopieren(ziel.s)
  Protected count
  DisableGadget(#ButtonForCopy, #True)
  ForEach tocopy()
    CopyFile(tocopy(), ziel)
    DeleteElement(tocopy())
    count + 1
    If count = 5
      ProcedureReturn 
    EndIf
  Next
  DisableGadget(#ButtonForCopy, #False)
EndProcedure
Wenn im Eventloop abbrechen geklickt wird, löschte den Timer, wenn Kopieren gedrückt wird,
erstellste den Timer.

Das Coden mußte schon selber machen :wink:

Gruß
Thomas

Re: ListViewGadget leeren und neu befüllen

Verfasst: 14.04.2010 14:36
von frankmannb
NicTheQuick hat geschrieben:Wichtig ist im Grunde, dass du während dem Kopieren keine Events verschluckst. Das heißt du musst auch während deiner Kopierschleife weiterhin 'WaitWindowEvent()' oder Konsorten aufrufen, damit ankommende Events abgearbeitet werden können. Tust du das nicht, sagt Windows "(Keine Rückmeldung)". Du kannst es deshalb so machen wir Kaeru es vorgeschlagen hat, also immer Stückweise kopieren und zwischendurch nochmal in die Eventschleife wechseln oder du machst es so, wie ich es machen würde, nämlich den kompletten Kopiervorgang in einem Thread abhandeln. Aber bevor du dich mit Threads rumschlägst, probiere erstmal die andere Methode. :allright:

Danke für die Info, aber wie springe ich wieder in dei Eventschleife ohne mit dem kopieren von vorne zu beginnen?

Re: ListViewGadget leeren und neu befüllen

Verfasst: 14.04.2010 14:38
von ts-soft
frankmannb hat geschrieben: Danke für die Info, aber wie springe ich wieder in dei Eventschleife ohne mit dem kopieren von vorne zu beginnen?
Siehe obigen Code, dort werden erledigte Elemente gelöscht, setzt voraus das die Linkliste am ende
nicht mehr benötigt wird, ansonsten eine extra dafür erstellen.

hab obigen code nochmal korrigiert.

Re: ListViewGadget leeren und neu befüllen

Verfasst: 14.04.2010 14:55
von AndyMars
Kurzer Einwurf: Wie gross sind denn die Dateien, die du da kopieren willst? Sollten sie sehr gross sein, kommt hinzu, dass dein Programm blockiert ist, während CopyFile eine solche Datei kopiert... (ausser du würdest Threads verwenden - was ich nicht würde - oder API CopyFileEx mit Callback...)

Re: ListViewGadget leeren und neu befüllen

Verfasst: 14.04.2010 14:58
von ts-soft
Je nach größe kann er ja in meiner Procedure reagieren. Count runter oder raufsetzen, Timer intervall
hoch oder runter. Das muß er sich schon so anpassen, das es paßt.

Re: ListViewGadget leeren und neu befüllen

Verfasst: 14.04.2010 15:11
von AndyMars
Ich würde gerne sehen, wie deine Procedure reagiert, wenn CopyFile eine 500MB Datei kopiert...

*TS-Soft freundlich knufft* (das Bild war übrigens sehr witzig ^^ hab mich gefragt was auf der anderen Seite wohl gewesen ist - könnte ja auch die Schweiz gewesen sein)

Das einzige saubere fände ich CopxFileEx mit Callback - ein Beispiel, nicht grad ausführbar, aber das Prinzip müsste ersichtlich sein:

Code: Alles auswählen

Procedure.l _CopyFileExCallback(TotalFileSize, totalbytetransfertalk, StreamSize, StreamBytesTransferred, dwStreamNumber.l, dwCallbackReason.l, hSourceFile.l, hDestinationFile.l, lpData.l, dummy1.l, dummy2.l, dummy3.l, dummy4.l)
  Shared KopierenAbbruch.l
  TotalFileSize_ = (TotalFileSize>>16) &$FFFFFFFF
  StreamSize_ = 100 * (StreamSize>>16) &$FFFFFFFF
  If TotalFileSize_ > 0 And StreamSize_ > 0
    percent = 100 * (StreamSize>>16) &$FFFFFFFF/(TotalFileSize>>16) &$FFFFFFFF
  Else
    percent = 100
  EndIf
  SetGadgetState(#Gadget_Main_ProgressBar, percent)
  ev=1
  While ev
  	ev=WindowEvent()
  	If ev=#PB_Event_Gadget
  		If EventGadget()=#Gadget_Main_ButtonAbbruch
  			KopierenAbbruch=1
  			ProcedureReturn 1 ;1=PROGRESS_CANCEL
  		EndIf
  	EndIf
  Wend
  ProcedureReturn 0 ;0=PROGRESS_CONTINUE
EndProcedure

Procedure.l _CopyFileEx(pSource.s,pTarget.s)
  ProcedureReturn CopyFileEx_(@pSource.s, @pTarget.s, @_CopyFileExCallback(), 0, 0, 0)
EndProcedure 
Edit: mom,mom, bin am recoden - hab mir ja wieder was eingebrockt... ;)

Re: ListViewGadget leeren und neu befüllen

Verfasst: 14.04.2010 15:14
von frankmannb
@AndyMars
Es sollen überwiegende mkv,mpg Dateien kopiert werden also 4,7GB. Sprich ich würde wenn ich den counter verwende es auf 1 belassen. Hast du eventuell ein Beispiel für eine Threadlösung.

Re: ListViewGadget leeren und neu befüllen

Verfasst: 14.04.2010 15:21
von ts-soft
Bei so grossen Dateien taugt mein Beispiel natürlich nicht. Da mußte die Datei in kleinen
Teilen kopieren. Ist ein bißchen komplizierter, entsprechendes Beispiel hab ich hier
irgendwann mal gepostet, finde es aber nicht wieder.

Also statt jedesmal 5 Dateien, eben 50 MB. CopyFile ist da natürlich nicht mehr zu
verwenden, sondern einlesen in Speicher und schreiben ist da angesagt.

Re: ListViewGadget leeren und neu befüllen

Verfasst: 14.04.2010 15:46
von ts-soft
Hier ein kleines, ungetestetes Beispiel, wie Du die Datei in stücken kopierst.
Im Timerereignis solange aufrufen, bis die Procedure #True zurückgibt, dann
die nächste Datei. Den rest mußte jetzt aber selber schaffen.

Code: Alles auswählen

Procedure CopyMyFile(source.s, dest.s, buffersize)
  Static FD, FS
  Protected *mem, result
  
  If Not FD
    FD = CreateFile(#PB_Any, dest)
  EndIf
  
  If Not FS
    FS = ReadFile(#PB_Any, source)
  EndIf
  
  *mem = AllocateMemory(buffersize)
  
  If *mem And FS And FD
    If Loc(FS) + buffersize < Lof(FS)
      ReadData(FS, *mem, buffersize)
      WriteData(FD, *mem, buffersize)
    Else
      buffersize = Lof(FS) - Loc(FD)
      If buffersize
        ReadData(FS, *mem, buffersize)
        WriteData(FD, *mem, buffersize)
      EndIf
      CloseFile(FS)
      CloseFile(FD)
      FD = 0
      FS = 0
      result = #True
    EndIf
    FreeMemory(*mem)
  EndIf
  ProcedureReturn result
EndProcedure
Gruß
Thomas

Re: ListViewGadget leeren und neu befüllen

Verfasst: 14.04.2010 15:53
von AndyMars
Och Thomas... ich war wieder mal langsamer... /:->

Getesteter Code :D :

Code: Alles auswählen

;CopyFileEx1004.pb
;Beispiel für WinAPI CopyFileEx
;PB 4,4

Procedure.l _CopyFileExCallback(TotalFileSize.q, TotalBytesTransferred.q, StreamSize.q, StreamBytesTransferred.q, dwStreamNumber.l, dwCallbackReason.l, hSourceFile.l, hDestinationFile.l, lpData.l)
  TotalMB=TotalFileSize/1048576
  MBTrans=TotalBytesTransferred/1048576
  SetGadgetText(0,Str(MBTrans)+"/"+Str(TotalMB)+" MB")
  ev=1
  While ev
  	ev=WindowEvent()
  	If ev=#PB_Event_Gadget
  		If EventGadget()=1 ;STOP-Button
  			ProcedureReturn 1 ;1=PROGRESS_CANCEL
  		EndIf
  	EndIf
  Wend
  ProcedureReturn 0 ;0=PROGRESS_CONTINUE
EndProcedure

Procedure.l _CopyFileEx(pSource.s,pTarget.s)
  Erg = CopyFileEx_(@pSource.s, @pTarget.s, @_CopyFileExCallback(), 0, 0, 0)
  ProcedureReturn Erg
EndProcedure

If OpenWindow(0,200,200,80,50,"CopyFileEx Test")
	TextGadget(0,5,5,60,20,"")
	ButtonGadget(1,5,25,60,20,"STOP")
	;hier natürlich bei euch existierende Pfade angeben (mit ner groooossen Datei)
	If _CopyFileEx("D:\_Downloads\3DMark06_v110_installer.exe","D:\_temp\3DMark06_v110_installer.exe")
		Debug "Kopieren erfolgreich"
	Else
		Debug "Fehler beim Kopieren"
	EndIf
	Repeat
		ev=WaitWindowEvent()
	Until ev=#PB_Event_CloseWindow 
	CloseWindow(0)
EndIf
Edit2: Evtl. müsste man einen Abbruch noch besser behandeln, damit nicht einfach ein Fehler auftritt - aber ihr dürft ruhig auch noch ein wenig hirnen...

Edit: Hach sind wir wieder produktiv! Gleich zwei Methoden im Angebot. Jetzt kann sich aber niemand mehr beschweren... ;)

Gruss Andy