Руководство - Доступ к памяти
Некоторые инструкции PureBasic, например, из библиотеки Cipher и многие вызовы API для операционной системы, требуют указателя на буфер памяти в качестве аргумента, а не непосредственно на данные. PureBasic предоставляет ряд инструкций для управления буферами памяти, для решения данных ситуаций.;- Директивы компилятора EnableExplicit ;- Константы ; Window (окна) Enumeration #WindowHex EndEnumeration ; Гаджеты Enumeration #GadgetFiles #GadgetOpen #GadgetClose #GadgetHex EndEnumeration ;- Переменные Define.l Event, EventWindow, EventGadget, EventType, EventMenu Define.l Length Define.s File Define *Buffer ;- Декларация Declare WindowCreate() Declare WindowResize() Declare FileClose() Declare FileDisplay() Declare FileRead() ;- Реализация Procedure WindowCreate() ; Создать окно. Protected.l Col Protected.s Label If OpenWindow(#WindowHex, 50, 50, 500, 400, "Hex View", #PB_Window_SystemMenu - #PB_Window_SizeGadget - #PB_Window_MinimizeGadget - #PB_Window_TitleBar) ; Установка минимального размера окна. WindowBounds(#WindowHex, 175, 175, #PB_Ignore, #PB_Ignore) ; Создать список проводника из корневого каталога вошедшего в систему пользователя. ExplorerListGadget(#GadgetFiles, 5, 5, 490, 175, GetHomeDirectory()) ; Кнопки. ButtonGadget(#GadgetOpen, 5, 185, 80, 25, "Open") ButtonGadget(#GadgetClose, 100, 185, 80, 25, "Close") ; Гаджет значка списка. ListIconGadget(#GadgetHex, 5, 215, 490, 180, "Offset", 80, #PB_ListIcon_AlwaysShowSelection - #PB_ListIcon_GridLines - #PB_ListIcon_FullRowSelect) ; Заголовки столбцов. For Col = 0 To 7 Label = RSet(Hex(Col, #PB_Byte), 2, "0") AddGadgetColumn(#GadgetHex, Col + 1, Label, 38) Next Col AddGadgetColumn(#GadgetHex, 9, "Text", 80) EndIf EndProcedure Procedure WindowResize() ; Изменить размеры Гаджетов, в связи с новым размером окна. Protected.l X, Y, W, H ; Список проводника. W = WindowWidth(#WindowHex) - 10 H = (WindowHeight(#WindowHex) - 35) / 2 ResizeGadget(#GadgetFiles, #PB_Ignore, #PB_Ignore, W, H) ; Кнопки Y = GadgetHeight(#GadgetFiles) + 10 ResizeGadget(#GadgetOpen, #PB_Ignore, Y, #PB_Ignore, #PB_Ignore) ResizeGadget(#GadgetClose, #PB_Ignore, Y, #PB_Ignore, #PB_Ignore) ; Список в виде иконок Y = (WindowHeight(#WindowHex) / 2) + 23 W = WindowWidth(#WindowHex) - 10 H = WindowHeight(#WindowHex) - (Y + 5) ResizeGadget(#GadgetHex, #PB_Ignore, Y, W, H) EndProcedure Procedure FileClose() ; Очистить список и освободить буфер памяти. Shared Length, *Buffer ClearGadgetItems(#GadgetHex) FillMemory(*Buffer, Length) FreeMemory(*Buffer) EndProcedure Procedure FileDisplay() ; Показать буфер файла в представлении списка. Shared Length, *Buffer Protected *Byte Protected Peek Protected.l Rows, Cols, Offset Protected.s OffsetString, Row, String ; Очистить текущее содержание. ClearGadgetItems(#GadgetHex) ; Цикл для строк. For Rows = 0 To Length - 1 Step 8 ; Очистить текстовое значение для каждой строки. String = "" ; Преобразовать значение смещения в строку фиксированной длины. Row = RSet(Hex(Rows, #PB_Long), 6, "0") + Chr(10) ; Цикл для столбцов. For Cols = 0 To 7 ; Вычислить смещение для текущего столбца. Offset = Rows + Cols ; Сравнить смещение с длиной файла. If Offset < Length ; Смещение является меньше, чем длина файла. ; Получить байт из буфера. *Byte = *Buffer + Offset Peek = PeekB(*Byte) ; Преобразовать байт в текст. Row + RSet(Hex(Peek, #PB_Byte), 2, "0") + Chr(10) ; Добавить символ к текстовой версии. Select Peek Case 0 To 31, 127 ; Непечатные символы. String + Chr(129) Default ; Печатные символы. String + Chr(Peek) EndSelect Else ; Смещение больше, чем длина файла. ; Добавить пустой столбец. Row + Chr(10) EndIf Next Cols ; Добавьте текстовую версию в конце шестнадцатеричных столбцов. Row + String ; Добавьте завершенную строку к представлению списка. AddGadgetItem(#GadgetHex, -1, Row) Next Rows EndProcedure Procedure FileRead() ; Считать файл в буфер памяти. Shared Length, File, *Buffer Protected.b ReadByte Protected.l FileNumber, ReadLong, Size ; Остановка, если файл пуст. If File = "" ProcedureReturn EndIf ; Остановка, если размер файла недопустим. Size = FileSize(File) If Size < 1 ProcedureReturn EndIf ; Открыть файл. FileNumber = OpenFile(#PB_Any, File) Length = Lof(FileNumber) If File And Length ; Выделить буфер памяти для содержания файла. *Buffer = AllocateMemory(Length) ; Считать файл в буфер. Length = ReadData(FileNumber, *Buffer, Length) EndIf ; Закрыть файл. CloseFile(FileNumber) EndProcedure ;- Главный код WindowCreate() ;- Цикл событий Repeat ; Получить параметры события. Event = WaitWindowEvent() EventGadget = EventGadget() EventType = EventType() EventWindow = EventWindow() ; События дескриптора. Select Event Case #PB_Event_Gadget If EventGadget = #GadgetFiles ; Ничего не делать. ElseIf EventGadget = #GadgetOpen File = GetGadgetText(#GadgetFiles) + GetGadgetItemText(#GadgetFiles, GetGadgetState(#GadgetFiles)) If FileSize(File) > 0 FileRead() FileDisplay() EndIf ElseIf EventGadget = #GadgetClose FileClose() ElseIf EventGadget = #GadgetHex ; Ничего не делать. EndIf Case #PB_Event_CloseWindow If EventWindow = #WindowHex CloseWindow(#WindowHex) Break EndIf Case #PB_Event_SizeWindow WindowResize() EndSelect ForEver
Навигация Руководства
< Чтение и запись файлов - Обзор - Динамическая нумерация с помощью #PB_Any >