Seite 2 von 2

Verfasst: 19.03.2008 13:04
von HeX0R
Ich würde so eine Funktion aber eher mittels eines Thread machen.
Fensterevents ins Nirvana zu bomben finde ich extrem unschön.

Beispiel:

Code: Alles auswählen

#FileName = "C:\Dokumente und Einstellungen\bratwurst\Eigene Dateien\Eigene Videos\HeX0R_Poppt_Svetlana.MPG"

Structure _MD5_THREAD_PARAMETER_
	FileName.s
	BufferSize.l
	ProgressBarGadget.l
	ProgressGadget.l
	SpeedGadget.l
	TimeGadget.l
	ResultGadget.l
EndStructure


Procedure.s ByteRechner(dSize.d)
	Protected Namen.q, i.l, Result.s, R.s = "0"

	Namen = 'KMGTPEZY'
	If dSize > 0.0
		i = 56
		While dSize > 1024 And i >= 0
			dSize / 1024
			Result = Chr((Namen >> i) & $FF)
			i - 8
		Wend
		R = StrD(dSize, 2) + " " + Result + "Byte"
	EndIf

	ProcedureReturn R
EndProcedure

Procedure MD5FileFingerPrintThread(*P._MD5_THREAD_PARAMETER_)
	Protected StartTime.l = Date()
	Protected FileID.l    = ReadFile(#PB_Any, *P\FileName)
	Protected *Buffer, FingerPrint.l
	Protected Progress.f, Elapsed.l, Speed.f, Remaining.f, Refresh.l = ElapsedMilliseconds() + 200

	If FileID
		*Buffer = AllocateMemory(*P\BufferSize)
		If *Buffer
			FingerPrint = ExamineMD5Fingerprint(#PB_Any)
			If FingerPrint
				While Eof(FileID) = 0
					NextFingerprint(FingerPrint, *Buffer, ReadData(FileID, *Buffer, *P\BufferSize))
					If Refresh < ElapsedMilliseconds()
						Elapsed  = Date() - StartTime
						Progress = Loc(FileID) / Lof(FileID) * 100
						If Elapsed ; to avoid division by zero
							Speed = Round(Loc(FileID) / Elapsed, #PB_Round_Nearest)
							If Speed ; prevent division by zero
								Remaining = Round((Lof(FileID) - Loc(FileID)) / Speed, #PB_Round_Nearest)
							EndIf
						EndIf
						If *P\ProgressBarGadget <> -1
							SetGadgetState(*P\ProgressBarGadget, Int(Progress))
						EndIf
						If *P\ProgressGadget <> -1
							SetGadgetText(*P\ProgressGadget, "Entire progress: " + StrF(Progress, 1) + "%")
						EndIf
						If *P\SpeedGadget <> -1
							SetGadgetText(*P\SpeedGadget, "Speed: " + ByteRechner(Speed) + "/sec")
						EndIf
						If *P\TimeGadget <> -1
							SetGadgetText(*P\TimeGadget, FormatDate("Elapsed: %hhh%iim%sss", Elapsed) + #CRLF$ + FormatDate("Remaining: %hhh%iim%sss", Remaining))
						EndIf
						Refresh = ElapsedMilliseconds() + 200
					EndIf
				Wend
				If *P\ResultGadget
					SetGadgetText(*P\ResultGadget, "Result: " + FinishFingerprint(FingerPrint))
				EndIf
			EndIf
			FreeMemory(*Buffer)
		EndIf
		CloseFile(FileID)
	EndIf

EndProcedure

Define ThreadID.l, Param._MD5_THREAD_PARAMETER_
Param\FileName          = #FileName
Param\BufferSize        = 16384
Param\ProgressBarGadget = 0
Param\ProgressGadget    = 1
Param\SpeedGadget       = 2
Param\TimeGadget        = 3
Param\ResultGadget      = 4

If OpenWindow(0, 0, 0, 400, 200, GetFilePart(Param\FileName), #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0))
	ProgressBarGadget(0,  10, 30, 250,  30, 0, 100)
	TextGadget       (1,  10, 10, 250,  20, "")
	TextGadget       (2,  10, 70, 250,  20, "")
	TextGadget       (3, 100,110, 200,  50, "")
	TextGadget       (4, 100, 170, 250, 20, "")

	ThreadID = CreateThread(@MD5FileFingerPrintThread(), @Param)

	Repeat
		Select WaitWindowEvent()
			Case #PB_Event_CloseWindow
				If IsThread(ThreadID)
					KillThread(ThreadID)
				EndIf
				Break
		EndSelect
	ForEver
EndIf

Verfasst: 19.03.2008 14:14
von AND51
Jedem das seine! :)
Ich persönlich finde, das ist ein Universalbefehl, der etwas zurückgeben soll, das kann man mit Threads nicht so einfach bewerkstelligen. Natürlich kann man die Prozedur auch als Thread aufrufen. Und Fensterevents kann jeder so handhaben, wie er möchte, dank des Callbacks stehen einem ja (fast?) alle Wege offen.

Sinn des Codes ist es ja auch, die Arbeitsweise an sich aufzuzeigen, damit andere davon lernen können. Was mann/frau draus macht, bleibt einem selbst überlassen.