Einsteiger-Kapitel - Strukturieren von Programmcode in Prozeduren

Wir schauen uns nun das Datei-Eigenschaften Beispiel erneut an. Dieses Mal um Prozeduren einzuführen und um uns um einige der zuvor festgestellten Einschränkungen zu kümmern.
  ; Die Struktur für die Datei-Informationen wie zuvor.
  Structure FILEITEM
    Name.s
    Attributes.i
    Size.q
    DateCreated.i
    DateAccessed.i
    DateModified.i
  EndStructure
  
  ; Dies ist eine Konstante zum Identifizieren des Fensters.
  Enumeration
    #WindowFiles
  EndEnumeration
  
  ; Dies ist eine Aufzählung (von Konstanten) zum Identifizieren der Gadgets, welche auf dem Fenster erscheinen.
  Enumeration
    #FolderButton
    #UpdateButton
    #FolderText
    #FilesList
  EndEnumeration
  
  Procedure FilesExamine(Folder.s, List Files.FILEITEM())
    ; Ermittelt die Datei-Eigenschaften vom Ordner in Dateien.
    
    Protected.l Result
    
    ; Löscht die aktuellen Inhalte.
    ClearList(Files())
    
    ; Öffnen des Verzeichnisses zum Auflisten seiner Inhalte.
    Result = ExamineDirectory(0, Folder, "*.*")  
    
    ; Ist dies ok, beginnen wir das Auflisten der Einträge.
    If Result
      ; Durchlauf bis NextDirectoryEntry(0) Null zurückgibt - was anzeigt, dass es keine weiteren Einträge gibt.
      While NextDirectoryEntry(0)
        ; Wenn der Verzeichnis-Eintrag eine Datei und kein Ordner ist.
        If DirectoryEntryType(0) = #PB_DirectoryEntry_File
          ; Fügt ein neues Element zur verketteten Liste hinzu.
          AddElement(Files())
          ; Und füllt sie mit den Eigenschaften der Datei.
          Files()\Name = DirectoryEntryName(0)
          Files()\Size = DirectoryEntrySize(0)
          Files()\Attributes = DirectoryEntryAttributes(0)
          Files()\DateCreated = DirectoryEntryDate(0, #PB_Date_Created)
          Files()\DateAccessed = DirectoryEntryDate(0, #PB_Date_Accessed)
          Files()\DateModified = DirectoryEntryDate(0, #PB_Date_Modified)
        EndIf
      Wend
      ; Schließt das Verzeichnis.
      FinishDirectory(0)
    EndIf
    
    ; Sortiert die Liste in alphabetisch aufsteigender Reihenfolge der Dateinamen.
    SortStructuredList(Files(), #PB_Sort_Ascending, OffsetOf(FILEITEM\Name), #PB_String)
  EndProcedure
  
  Procedure.s FolderSelect(Folder.s)
    ; Zeigt einen Pfad-Requester an und gibt den neuen Dateipfad zurück - oder den alten, wenn der Requester abgebrochen wurde.
    Protected.s SelectedPath
    
    SelectedPath = PathRequester("Choose a folder.", Folder)
    
    If SelectedPath = ""
      SelectedPath = Folder
    EndIf
    
    ProcedureReturn SelectedPath
  EndProcedure
  
  Procedure LabelUpdate(Folder.s)
    ; Aktualisiert die Verzeichnis-Beschriftung.
    SetGadgetText(#FolderText, Folder)
  EndProcedure
  
  Procedure ListLoad(ListView.l, List Files.FILEITEM())
    ; Lädt die Datei-Eigenschaften aus der Liste Files() in die Listenanzeige #FilesList.
    Protected.s Access, Attrib, Create, Folder, Modify, Msg, Num, Size
    
    ; Entfernt die vorherigen Inhalte.
    ClearGadgetItems(ListView)
    
    ForEach Files()
      ; Anzeigen der Eintragsnummer und des Dateinamens.
      Num = StrU(ListIndex(Files()) + 1)
      
      ; Diese Zeilen konvertieren die drei Datumswerte in eine gebräuchlichere Ansicht.
      Create = FormatDate("%dd/%mm/%yyyy", Files()\DateCreated)
      Access = FormatDate("%dd/%mm/%yyyy", Files()\DateAccessed)
      Modify = FormatDate("%dd/%mm/%yyyy", Files()\DateModified)
      
      ; Konvertiert die Dateigröße in einen String - genauso wie vorhin den Index-Wert,
      ; lässt aber Platz für die maximale Größe eines Quad-Wertes.
      Size = StrU(Files()\Size)
      
      ; Konvertiert die Attribute vorerst in einen String.
      Attrib = StrU(Files()\Attributes)
      
      ; Erstellt einen String für die gesamte Zeile.
      ; Das Zeilenvorschub-Zeichen 'Chr(10)' sagt dem Gadget, dass es zur nächsten Spalte springen soll.
      Msg = Num + Chr(10) + Files()\Name + Chr(10) + Create + Chr(10) + Access + Chr(10) + Modify + Chr(10) + Attrib + Chr(10) + Size
      
      ; Hinzufügen der Zeile zum Listen-Gadget.
      AddGadgetItem(#FilesList, -1, Msg)
    Next Files()
  EndProcedure
  
  Procedure WindowCreate()
    ; Erstellt das wdwFiles Fenster.
    Protected Flags
    
    ; Diese Zeile definiert ein Flag für die Fenster-Attribute, indem die gewünschten Attribut-Konstanten mittels 'OR' (hier das '|' Zeichen) miteinander verknüpft werden.
    Flags = #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget| #PB_Window_TitleBar
    
    ; Öffnet ein Fenster.
    OpenWindow(#WindowFiles, 50, 50, 450, 400, "File Properties", Flags)
    ; Ein Schalter zum Öffnen eines Ordners.
    ButtonGadget(#FolderButton, 5, 5, 100, 30, "Select Folder")
    ; Ein Schalter zum Aktualisieren der Liste.
    ButtonGadget(#UpdateButton, 112, 5, 100, 30, "Update List")
    ; Ein Text-Gadget zum Anzeigen des Verzeichnis-Namens.
    TextGadget(#FolderText, 5, 40, 400, 25, "")
    ;Ein ListIcon Gadget, welches die Dateiliste und die Eigenschaften beinhaltet.
    ListIconGadget(#FilesList, 5, 70, 400, 326, "#", 35)
    ; Hinzufügen von Spalten zum ListIconGadget, welche jede Eigenschaft darstellen sollen.
    AddGadgetColumn(#FilesList, 1, "Name", 200)
    AddGadgetColumn(#FilesList, 2, "Created", 100)
    AddGadgetColumn(#FilesList, 3, "Accessed", 100)
    AddGadgetColumn(#FilesList, 4, "Modified", 100)
    AddGadgetColumn(#FilesList, 5, "Attributes", 150)
    AddGadgetColumn(#FilesList, 6, "Size", 100)
  EndProcedure
  
  Procedure WindowDestroy()
    ; Schließt das Fenster.
    ; Falls nötig, können Sie hier auch andere "Aufräumarbeiten" durchführen.
    CloseWindow(#WindowFiles)
  EndProcedure
  
  Procedure WindowResize()
    ; Verändert die Größe der Fenster-Gadgets entsprechend der neuen Fenstergröße.
    ResizeGadget(#FolderText, #PB_Ignore, #PB_Ignore, WindowWidth(#WindowFiles) - 10, #PB_Ignore)
    ResizeGadget(#FilesList, #PB_Ignore, #PB_Ignore, WindowWidth(#WindowFiles) - 10, WindowHeight(#WindowFiles) - 74)
  EndProcedure
  
  ;- Hauptteil
  ; Jetzt definieren wir eine Liste von Dateien unter Verwendung der zuvor spezifizierten Struktur.
  NewList Files.FILEITEM()
  
  ; Und einige Variablen für weitere Dinge.
  Define.s Folder
  Define.l Event, EventWindow, EventGadget, EventType, EventMenu
  
  ; Diese Funktion ermittelt das Benutzer-Verzeichnis des angemeldeten Anwenders.
  Folder = GetHomeDirectory()
  
  ; Erstellen des Fensters und Festlegen der anfänglichen Inhalte.
  WindowCreate()
  WindowResize()
  LabelUpdate(Folder)
  FilesExamine(Folder, Files())
  ListLoad(#FilesList, Files())
  
  ;- Ereignis-Schleife
  Repeat
    ; Warten bis ein neues Fenster- oder Gadget-Ereignis auftritt.
    Event = WaitWindowEvent()
    EventWindow = EventWindow()
    EventGadget = EventGadget()
    EventType = EventType()
    
    ; Hier beginnen nun die entsprechenden Aktionen.
    Select Event
      Case #PB_Event_Gadget
        ; Ein Gadget-Ereignis ist aufgetreten.

        If EventGadget = #FolderButton
          ; Der Verzeichnis-Schalter wurde angeklickt.
          Folder = FolderSelect(Folder)
          LabelUpdate(Folder)
          FilesExamine(Folder, Files())
          ListLoad(#FilesList, Files())
          
        ElseIf EventGadget = #UpdateButton
          ; Der Aktualisieren-Schalter wurde angeklickt.
          FilesExamine(Folder, Files())
          ListLoad(#FilesList, Files())
          
        ElseIf EventGadget = #FolderText
          ; Tue nichts hier.
          
        ElseIf EventGadget = #FilesList
          ; Tue nichts hier.
          
        EndIf
        
      Case #PB_Event_SizeWindow
        ; Das Fenster wurde verschoben oder in der Größe verändert.
        If EventWindow = #WindowFiles
          WindowResize()  
        EndIf
        
      Case #PB_Event_CloseWindow
        ; Das Fenster wurde geschlossen.
        If EventWindow = #WindowFiles
          WindowDestroy()
          Break
        EndIf
    EndSelect
  ForEver
Zuvor haben wir vier Einschränkungen dieses Programms erwähnt. Diese neue Version verwendet Prozeduren um drei davon anzusprechen.

1) Sie konnten keinen Ordner zum Anzeigen auswählen.
Die "FolderSelect" Prozedur zeigt einen Pfad-Requester, um dem Anwender die Auswahl eines Verzeichnisses zu ermöglichen. Die Variable "Folder" wird mit dem Ergebnis dieser Prozedur aktualisiert. Der Schalter ruft auch "LabelUpdate", "FilesExamine" und "ListLoad" auf, um die Inhalte des neuen Verzeichnisses im Fenster anzuzeigen.

2) Sie konnten den Listen-Inhalt nicht aktualisieren, ohne das Programm zu schließen und neu zu starten.
Jetzt werden, wenn der "Update List" Schalter angeklickt wurde, "FilesExamine" und "ListLoad" erneut aufgerufen, um die Anzeige zu aktualisieren.

3) Wenn Sie die Fenstergröße verändert haben, wurde die Gadgets nicht entsprechend angepasst.
Die "WindowResize" Prozedur wird in der Ereignis-Schleife aufgerufen, um die Gadgets in der Größe anzupassen, wenn das Fenster in der Größe verändert wurde. Auch wenn dieses Programm dies nicht wirklich benötigt, so wird diese Prozedur nach dem Aufruf von "WindowCreate" aufgerufen, um sicherzustellen, dass die Gadgets auch zu Beginn die richtige Größe haben.

Beachten Sie, wie einige der Prozeduren mehr als einmal aufgerufen werden, um ähnliche aber nicht identische Funktionen auszuführen. Dies verbessert die Effizienz des Programms.

Wir haben eine letzte Einschränkung, welche wir in einem späteren Artikel überwinden werden.

Einsteiger-Kapitel Navigation

< Vorheriges: Anzeigen von Grafik-Ausgabe & einfaches Zeichnen | Überblick | Nächstes: Compiler-Direktiven >