Учебно-тренировочная работа
Код:
; PureBasic Visual Designer v3.95 build 1485 (PB4Code)
Import "Kernel32.lib"
SetFilePointerEx.i(*hFile,liDistanceToMove.q,*lpNewFilePointer,dwMoveMethod.l)
EndImport
;- Window Constants
;
Enumeration
#Window_0
EndEnumeration
;- Gadget Constants
;
Enumeration
#Text_0
#Text_1
#Text_Size
#Text_2
#Text_Count
#Text_Msg
#Text_Help
#String_0
#String_1
#Button_Select
#Button_Start
#Button_Stop
#Button_Help
#ProgressBar_0
EndEnumeration
Global lWorkThreadStarted.b ; рабочий поток запущен
Global lWorkThreadStop.b ; команда на останов потока
Global nWorkThread.l
Global iSectorSize.i ;размер сектора в байтах - нужен для режима #FILE_FLAG_NO_BUFFERING
Define Filename$
Procedure.s GetSysErrorText(ErrCode)
Define result.s=""
*Memory = AllocateMemory (255)
length = FormatMessage_ (#FORMAT_MESSAGE_FROM_SYSTEM, #Null, ErrCode, 0, *Memory, 255, #Null)
result=PeekS (*Memory, length - 2)
FreeMemory (*Memory)
ProcedureReturn result
EndProcedure
Procedure FatalError()
Protected Result$, Line
Result$="FatalError(): "
Line = ErrorLine()
If Line>=0
Result$+" в строке "+Str(Line)+", файла: "+ErrorFile()
EndIf
Result$+" Ошибка типа: "+Chr(34)+ErrorMessage()+Chr(34)
MessageRequester("Фатальная ошибка выполнения", Result$, #PB_MessageRequester_Ok )
End
EndProcedure
Procedure SaveParams(IniFileName.s) ; сохранить параметры текущей сессии
; сохранить параметры программы
If CreatePreferences(IniFileName)
PreferenceGroup("Values")
WritePreferenceString("File", GetGadgetText(#String_0) )
ClosePreferences()
EndIf
EndProcedure
Procedure.s IntToTrain(In.q, FieldLen.i, delimiter.s) ; Входное число, длина поля ("триады"), разделитель триад
tmp$=Str(In)
tmpLen=Len(tmp$)
dlmLen=Len(delimiter)
NewLen=0
; количество "триад" и новая длина
FieldQty=Int(tmpLen/FieldLen)
NewLen=FieldQty*FieldLen
n=tmpLen % FieldLen
If n>0
FieldQty+1
NewLen+n
EndIf
NewLen+(FieldQty-1)*dlmLen
*Result=AllocateMemory(NewLen+1)
FillMemory(*Result, NewLen+1)
pr=0 ;pointer of result
If n>0 ; перенос первой неполной триады
CopyMemory(@tmp$, *Result, n)
pr+n
If FieldQty>1
CopyMemory(@delimiter, *Result+pr, dlmLen)
pr+dlmLen
EndIf
EndIf
p=n+1
While p<tmpLen ; перенос полных триад
CopyMemory(@tmp$+p-1, *Result+pr, FieldLen)
pr+FieldLen
If pr<NewLen
CopyMemory(@delimiter, *Result+pr, dlmLen)
pr+dlmLen
EndIf
p+FieldLen
Wend
ProcedureReturn PeekS(*Result , NewLen )
EndProcedure
Procedure getMyFile()
Filename$ = OpenFileRequester("Выбрать файл для проверки", "", "Все файлы|*.*", 0)
If Len(Filename$)>0
SetGadgetText(#String_0,Filename$)
EndIf
EndProcedure
Procedure showFileSize()
Protected Filename$=GetGadgetText(#String_0)
If Mid(Filename$,2,2)=":\" ;есть буква диска
Protected SectorsPerCluster, BytesPerSector, NumberOfFreeClusters, TotalNumberOfClusters
If GetDiskFreeSpace_( Mid(Filename$,1,3), @SectorsPerCluster, @BytesPerSector, @NumberOfFreeClusters, @TotalNumberOfClusters)
iSectorSize=BytesPerSector
EndIf
Else
SetGadgetText(#Text_Msg, "Не могу опознать букву диска")
ProcedureReturn
EndIf
Protected Result.q = FileSize(GetGadgetText(#String_0))
If Result<0
SetGadgetText(#Text_Msg, "Файл не найден")
SetGadgetText(#Text_Size, "")
Else
SetGadgetText(#Text_Size, IntToTrain(Result, 3, " "))
SetGadgetText(#Text_Msg, "")
DisableGadget(#Button_Start,0)
EndIf
SetGadgetText(#Text_Count, "")
SetGadgetState(#ProgressBar_0, 100)
EndProcedure
Procedure Start(*Value)
lWorkThreadStarted=#True
SetGadgetText(#Text_Msg, "")
;открыть файл
File$=GetGadgetText(#String_0)
Handle=CreateFile_(@File$,#GENERIC_READ,#FILE_SHARE_READ,0,#OPEN_EXISTING,#FILE_FLAG_NO_BUFFERING,0)
If Handle=#INVALID_HANDLE_VALUE
ErrCode=GetLastError_()
SetGadgetText(#Text_Msg, "Ошибка открытия файла ErrCode="+Str(ErrCode)+":"+GetSysErrorText(ErrCode))
CloseHandle_(Handle)
Else
DisableGadget(#Button_Start,1)
DisableGadget(#Button_Stop,0)
;qFileSize.q=GetFileSize_(Handle, #NUL) ;длина файла
qFileSize.q=0
GetFileSizeEx_(Handle,@qFileSize)
SetGadgetText(#Text_Size, IntToTrain(qFileSize, 3, " ")) ;Str(qFileSize))
KSize=iSectorSize*256 ;размер буфера
*Buffer1=AllocateMemory(KSize)
If *Buffer1
nReaded.l=0 ;для возврата количества реально прочитаных байт
qCount.q=0 ;прочитано байт от начала файла
iOk.i=1 ;флаг успешного завершения операции
While qCount<qFileSize
If SetFilePointerEx(Handle, qCount, #NUL, #FILE_BEGIN) = 0
ErrCode=GetLastError_()
SetGadgetText(#Text_Msg, "Ошибка установки позиции чтения файла Err."+Str(ErrCode)+":"+GetSysErrorText(ErrCode))
EndIf
If ReadFile_(Handle,*Buffer1,KSize,@nReaded,0) = 0
ErrCode=GetLastError_()
SetGadgetText(#Text_Msg, "Ошибка чтения файла. ErrCode="+Str(ErrCode)+":"+GetSysErrorText(ErrCode))
iOk=0
Break
EndIf
qCount+nReaded
SetGadgetState(#ProgressBar_0, Int(qCount/qFileSize*100))
SetGadgetText(#Text_Count, Str(Int(qCount/qFileSize*100))+"% "+IntToTrain(qCount, 3, " ")) ;Str(qCount))
If lWorkThreadStop ;прервать проверку
SetGadgetText(#Text_Msg, "Чтение файла прервано по требованию пользователя")
iOk=0
Break
EndIf
Wend
FreeMemory(*Buffer1)
If iOk
SetGadgetText(#Text_Msg, "Читабельность файла - Ok")
EndIf
Else
SetGadgetText(#Text_Msg, "Ошибка при выделении памяти под буфер. ErrCode="+Str(ErrCode)+":"+GetSysErrorText(ErrCode))
EndIf
CloseHandle_(Handle)
DisableGadget(#Button_Start,0)
DisableGadget(#Button_Stop,1)
DisableGadget(#ProgressBar_0,1)
EndIf
lWorkThreadStarted=#False
EndProcedure
Procedure Open_Window_0()
Protected Result.b= #False
If OpenWindow(#Window_0, 281, 107, 570, 99, "Проверка читабельности файла (r) SadStar", #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered)
TextGadget(#Text_0, 10, 10, 50, 20, "Файл : ", #PB_Text_Right)
StringGadget(#String_0, 60, 10, 440, 20, "")
TextGadget(#Text_1, 10, 40, 50, 20, "Размер : ", #PB_Text_Right)
TextGadget(#Text_Size, 60, 40, 110, 20, "0", #PB_Text_Right)
TextGadget(#Text_2, 10, 60, 50, 20, "Считано : ", #PB_Text_Right)
TextGadget(#Text_Count, 60, 60, 110, 20, "0", #PB_Text_Right)
TextGadget(#Text_Msg, 180, 40, 320, 35, "0")
SetGadgetColor(#Text_Msg, #PB_Gadget_FrontColor, #Red)
ButtonGadget(#Button_Select, 510, 10, 50, 20, ". . .")
ButtonGadget(#Button_Start, 510, 43, 50, 20, "Start")
DisableGadget(#Button_Start,1)
ButtonGadget(#Button_Stop, 510, 75, 50, 20, "Stop")
DisableGadget(#Button_Stop,1)
ProgressBarGadget(#ProgressBar_0, 60, 80, 440, 10, 0, 10, #PB_ProgressBar_Smooth )
SetGadgetAttribute(#ProgressBar_0, #PB_ProgressBar_Minimum, 0)
SetGadgetAttribute(#ProgressBar_0, #PB_ProgressBar_Maximum, 100)
SetGadgetState(#ProgressBar_0, 100)
DisableGadget(#ProgressBar_0,1)
ButtonGadget(#Button_Help, 5, 75, 50, 20, "???" , #PB_Button_Toggle)
TextGadget(#Text_Help, 60, 100, 440, 140, "TextGadget Border", #PB_Text_Border)
Text$="Эта утилита проверяет читабельность файла с носителя."+#CRLF$
Text$+"Просто читает файл от начала и до конца."+#CRLF$
Text$+"Если попадется 'битый' участок файла - остановится по ошибке."+#CRLF$
Text$+"Обычно я проверял читабельность файлов (например - киношки на CD/DVD) методом копирования."+#CRLF$
Text$+"Но для больших файлов нужно большое место для приема файлов."+#CRLF$
Text$+"Да еще антивирус кидается его проверять..."+#CRLF$
Text$+"Т.ч. с этой утилитой будет проще жить."+#CRLF$
Text$+"20/06/2012"+#CRLF$
Text$+"SadStar"+#CRLF$
SetGadgetText(#Text_Help, Text$)
Result=#True
EndIf
ProcedureReturn Result
EndProcedure
OnErrorCall(@FatalError())
ProgName$ = ProgramFilename() ;полное имя файла самой исполняемой программы
IniFileName$ = Left(ProgName$, Len(ProgName$)-3)+"ini" ;полное имя ini-файла
If Not Open_Window_0(): End: EndIf
;{ Восстановление параметров
If OpenPreferences(IniFileName$)
If PreferenceGroup("Values")
; восстанавливаем параметры последнего сеанса работы с программой
SetGadgetText(#String_0, ReadPreferenceString("File", ""))
EndIf
ClosePreferences()
EndIf
;}
showFileSize()
;{- Event loop
Repeat
Event = WaitWindowEvent() ; ждать события
EventWindow = EventWindow() ; какое окно поимело событие
Select Event
; ------------------------------
Case #PB_Event_Gadget
EventGadget = EventGadget()
EventType = EventType()
If EventGadget = #Button_Select
getMyFile()
showFileSize()
ElseIf EventGadget = #Button_Start
; запустить поток обработки
lWorkThreadStarted=#False
lWorkThreadStop=#False
nWorkThread = CreateThread(@Start(), 0)
If Not nWorkThread
SetGadgetText(#Text_Msg, "Поток обработки не создан. ErrCode="+Str(ErrCode)+":"+GetSysErrorText(ErrCode))
EndIf
ElseIf EventGadget = #Button_Stop
; остановить поток обработки
lWorkThreadStop=#True
ElseIf EventGadget = #Button_Help
If GetGadgetState(#Button_Help)
ResizeWindow(#Window_0, #PB_Ignore, #PB_Ignore, #PB_Ignore, WindowHeight(#Window_0) +150)
Else
ResizeWindow(#Window_0, #PB_Ignore, #PB_Ignore, #PB_Ignore, WindowHeight(#Window_0) -150)
EndIf
EndIf
; ----------------------------
Case #PB_Event_CloseWindow
If EventWindow = #Window_0
SaveParams(IniFileName$)
If lWorkThreadStarted And IsThread(nWorkThread)
KillThread(nWorkThread)
EndIf
CloseWindow(#Window_0)
Break
EndIf
EndSelect
ForEver
;}
End