Einsteiger-Kapitel - Speicher-Zugriff
Einige PureBasic-Anweisungen, zum Beispiel die aus der Cipher Bibliothek, und viele Betriebssystem-API-Aufrufe benötigen einen Zeiger (Pointer) auf einen Speicherpuffer als ein Argument, anstatt die Daten direkt selbst. PureBasic bietet eine Reihe von Anweisungen zum Manipulieren des Speicherpuffers, um dies zu erleichtern.;- Compiler-Direktiven EnableExplicit ;- Konstanten ; Fenster Enumeration #WindowHex EndEnumeration ; Gadgets Enumeration #GadgetFiles #GadgetOpen #GadgetClose #GadgetHex EndEnumeration ;- Variablen Define.l Event, EventWindow, EventGadget, EventType, EventMenu Define.l Length Define.s File Define *Buffer ;- Deklarationen Declare WindowCreate() Declare WindowResize() Declare FileClose() Declare FileDisplay() Declare FileRead() ;- Implementierung Procedure WindowCreate() ; Erstellen des Fensters. 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) ; Festlegen des Mindest-Fenstergröße. WindowBounds(#WindowHex, 175, 175, #PB_Ignore, #PB_Ignore) ; Erstellen der Explorer Liste und Einstellen auf das Benutzer-Verzeichnis. ExplorerListGadget(#GadgetFiles, 5, 5, 490, 175, GetHomeDirectory()) ; Schalter. ButtonGadget(#GadgetOpen, 5, 185, 80, 25, "Open") ButtonGadget(#GadgetClose, 100, 185, 80, 25, "Close") ; ListIcon Gadget. ListIconGadget(#GadgetHex, 5, 215, 490, 180, "Offset", 80, #PB_ListIcon_AlwaysShowSelection | #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect) ; Spalten-Überschriften. 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() ; Verändern der Gadgetgröße auf die neue Fenstergröße. Protected.l X, Y, W, H ; Explorer Liste W = WindowWidth(#WindowHex) - 10 H = (WindowHeight(#WindowHex) - 35) / 2 ResizeGadget(#GadgetFiles, #PB_Ignore, #PB_Ignore, W, H) ; Schalter Y = GadgetHeight(#GadgetFiles) + 10 ResizeGadget(#GadgetOpen, #PB_Ignore, Y, #PB_Ignore, #PB_Ignore) ResizeGadget(#GadgetClose, #PB_Ignore, Y, #PB_Ignore, #PB_Ignore) ; ListIcon Anzeige Y = (WindowHeight(#WindowHex) / 2) + 23 W = WindowWidth(#WindowHex) - 10 H = WindowHeight(#WindowHex) - (Y + 5) ResizeGadget(#GadgetHex, #PB_Ignore, Y, W, H) EndProcedure Procedure FileClose() ; Löscht die Listen-Anzeige und gibt den Speicherpuffer frei. Shared Length, *Buffer ClearGadgetItems(#GadgetHex) FillMemory(*Buffer, Length) FreeMemory(*Buffer) EndProcedure Procedure FileDisplay() ; Anzeigen des Datei-Puffers in der Listen-Anzeige. Shared Length, *Buffer Protected *Byte Protected Peek Protected.l Rows, Cols, Offset Protected.s OffsetString, Row, String ; Löschen der aktuellen Inhalte. ClearGadgetItems(#GadgetHex) ; Die Zeilen durchlaufen. For Rows = 0 To Length - 1 Step 8 ; Löschen des Text-Wertes jeder Zeile. String = "" ; Konvertieren des Offset-Wertes in einen String fester Länge. Row = RSet(Hex(Rows, #PB_Long), 6, "0") + Chr(10) ; Die Spalten durchlaufen. For Cols = 0 To 7 ; Offset für die aktuelle Spalte berechnen. Offset = Rows + Cols ; Den Offset mit der Datei-Größe vergleichen. If Offset < Length ; Der Offset ist kleiner als die Länge der Datei. ; Das Byte vom Puffer ermitteln. *Byte = *Buffer + Offset Peek = PeekB(*Byte) ; Das Byte in Text konvertieren. Row + RSet(Hex(Peek, #PB_Byte), 2, "0") + Chr(10) ; Das Zeichen zur Text-Version hinzufügen. Select Peek Case 0 To 31, 127 ; Nicht druckbare/darstellbare Zeichen. String + Chr(129) Default ; Darstellbare Zeichen. String + Chr(Peek) EndSelect Else ; Der Offset ist größer als die Länge der Datei. ; Eine leere Spalte hinzufügen. Row + Chr(10) EndIf Next Cols ; Die Text-Version am Ende der Hex-Spalten hinzufügen. Row + String ; Hinzufügen der komplettierten Zeile zur Listen-Anzeige. AddGadgetItem(#GadgetHex, -1, Row) Next Rows EndProcedure Procedure FileRead() ; Lesen der Datei in den Speicherpuffer. Shared Length, File, *Buffer Protected.b ReadByte Protected.l FileNumber, ReadLong, Size ; Stoppen wenn die Datei leer ist. If File = "" ProcedureReturn EndIf ; Stoppen wenn die Dateigröße ungültig ist. Size = FileSize(File) If Size < 1 ProcedureReturn EndIf ; Öffnen der Datei. FileNumber = OpenFile(#PB_Any, File) Length = Lof(FileNumber) If File And Length ; Einen Speicherpuffer reservieren, um darin die Datei aufzunehmen. *Buffer = AllocateMemory(Length) ; Lesen der Datei in den Puffer. Length = ReadData(FileNumber, *Buffer, Length) EndIf ; Schließen der Datei. CloseFile(FileNumber) EndProcedure ;- Hauptteil WindowCreate() ;- Ereignis-Schleife Repeat ; Ermitteln der Ereignis-Parameter. Event = WaitWindowEvent() EventGadget = EventGadget() EventType = EventType() EventWindow = EventWindow() ; Verarbeiten der Ereignisse. Select Event Case #PB_Event_Gadget If EventGadget = #GadgetFiles ; Tue nichts. ElseIf EventGadget = #GadgetOpen File = GetGadgetText(#GadgetFiles) + GetGadgetItemText(#GadgetFiles, GetGadgetState(#GadgetFiles)) If FileSize(File) > 0 FileRead() FileDisplay() EndIf ElseIf EventGadget = #GadgetClose FileClose() ElseIf EventGadget = #GadgetHex ; Tue nichts. EndIf Case #PB_Event_CloseWindow If EventWindow = #WindowHex CloseWindow(#WindowHex) Break EndIf Case #PB_Event_SizeWindow WindowResize() EndSelect ForEver
Einsteiger-Kapitel Navigation
< Vorheriges: Lesen und Schreiben von Dateien | Überblick | Nächstes: Dynamische Nummerierung mittels #PB_Any >