Ich hab mir ein kleines Logsystem gebastelt das in das nächste Release von Simple Container eingebaut wird.
Das System ist einfach, kann beliebig viele Log - Prioritäten verwalten (vordefiniert: Info, Warning, Error) und diese auch einfach wiedergeben. Zudem lässt es sich bequem an/ausschalten, ich finde das einfach komfortabler beim Einbau in andere Projekte.
Einfach mal ausprobieren, ich denke das ganze ist selbsterklärend und gut dokumentiert:
Bugs, Kommentare, Wünsche, ... einfach hier posten

Logger.pbi:
Code: Alles auswählen
; ------------------------------------------------------------------------------------
; Einfaches Logsystem
; Author: Alexander Aigner
; PB 4.4+ x86/x64 Ascii/Unicode
; ------------------------------------------------------------------------------------
XIncludeFile "LinkedList.pbi"
; EnableExplicit
Structure Logger_Entry
Priority.l
Time.l
*Message
EndStructure
Structure Logger_Data
LogList.i
MinViewPriority.l
*Current.Logger_Entry
Enable.a
EndStructure
Enumeration
#Logger_Info
#Logger_Warning
#Logger_Error
EndEnumeration
; ------------------------------------------------------------------------------------
; Erstellt einen neuen Logger
;
; Rückgabe: Logger - Handle
; ------------------------------------------------------------------------------------
Procedure Logger_New()
Protected *Logger.Logger_Data = AllocateMemory(SizeOf(Logger_Data))
With *Logger
\LogList = LL_New()
\Enable = #True
EndWith
ProcedureReturn *Logger
EndProcedure
; ------------------------------------------------------------------------------------
; Löscht alle Einträge im Logger
; *Logger: Logger Handle
;
; Rückgabe: 0
; ------------------------------------------------------------------------------------
Procedure Logger_Clear(*Logger.Logger_Data)
Protected *LogEntry.Logger_Entry
With *Logger
LL_Reset(\LogList)
While LL_Next(\LogList)
*LogEntry = LL_Get(\LogList)
LL_Delete(\LogList)
FreeMemory(*LogEntry\Message)
FreeMemory(*LogEntry)
Wend
EndWith
EndProcedure
; ------------------------------------------------------------------------------------
; Gibt den Logger frei
; *Logger: Logger Handle
;
; Rückgabe: 0
; ------------------------------------------------------------------------------------
Procedure Logger_Free(*Logger.Logger_Data)
With *Logger
Logger_Clear(*Logger)
LL_Free(\LogList)
FreeMemory(*Logger)
EndWith
EndProcedure
; ------------------------------------------------------------------------------------
; Aktiviert/Deaktiviert den Logger
; *Logger: Logger Handle
; Enable: #False: Logger ist deaktiviert, sonst aktiviert
;
; Rückgabe: 0
; ------------------------------------------------------------------------------------
Procedure Logger_Enable(*Logger.Logger_Data, Enable = #True)
With *Logger
\Enable = Enable
EndWith
EndProcedure
; ------------------------------------------------------------------------------------
; Erstellt einen neuen Eintrag im Logger
; *Logger: Logger Handle
; Eintrag: Log - Nachricht
; Priority: Priorität des Eintrags
;
; Rückgabe: 0
; ------------------------------------------------------------------------------------
Procedure Logger_Log(*Logger.Logger_Data, Message$, Priority = #Logger_Info)
Protected *LogEntry.Logger_Entry
With *Logger
If Message$ And \Enable
LL_Last(\LogList)
*LogEntry = AllocateMemory(SizeOf(Logger_Entry))
*LogEntry\Time = Date()
*LogEntry\Priority = Priority
*LogEntry\Message = AllocateMemory(StringByteLength(Message$) + SizeOf(Character))
PokeS(*LogEntry\Message, Message$)
LL_Add(\LogList)
LL_Set(\LogList, *LogEntry)
EndIf
EndWith
EndProcedure
; ------------------------------------------------------------------------------------
; Startet eine Auflistung aller Einträge im Logger
; *Logger: Logger Handle
; MinimumViewPriority: Minimale Priorität der Einträge die aufgelistet werden sollen
;
; Rückgabe: 0
; ------------------------------------------------------------------------------------
Procedure Logger_StartView(*Logger.Logger_Data, MinimumViewPriority = #Logger_Info)
With *Logger
LL_Reset(\LogList)
\MinViewPriority = MinimumViewPriority
EndWith
EndProcedure
; ------------------------------------------------------------------------------------
; Läd den nächsten Eintrag aus dem Logger
; *Logger: Logger Handle
;
; Rückgabe: #True wenn Eintrag vorhanden, sonst #False
; ------------------------------------------------------------------------------------
Procedure Logger_ViewNext(*Logger.Logger_Data)
Protected RtVar, *LogEntry.Logger_Entry
With *Logger
\Current = #Null
While LL_Next(\LogList)
*LogEntry = LL_Get(\LogList)
If *LogEntry\Priority >= \MinViewPriority
\Current = *LogEntry
RtVar = #True
Break
EndIf
Wend
EndWith
ProcedureReturn RtVar
EndProcedure
; ------------------------------------------------------------------------------------
; Läd die Zeit des aktuellen Eintrags
; *Logger: Logger Handle
;
; Rückgabe: Zeit
; ------------------------------------------------------------------------------------
Procedure Logger_GetTime(*Logger.Logger_Data)
With *Logger
If \Current
ProcedureReturn \Current\Time
EndIf
EndWith
EndProcedure
; ------------------------------------------------------------------------------------
; Läd die Priorität des aktuellen Eintrags
; *Logger: Logger Handle
;
; Rückgabe: Priorität
; ------------------------------------------------------------------------------------
Procedure Logger_GetPriority(*Logger.Logger_Data)
With *Logger
If \Current
ProcedureReturn \Current\Priority
EndIf
EndWith
EndProcedure
; ------------------------------------------------------------------------------------
; Läd die Nachricht des aktuellen Eintrags
; *Logger: Logger Handle
;
; Rückgabe: Nachricht
; ------------------------------------------------------------------------------------
Procedure.s Logger_GetMessage(*Logger.Logger_Data)
With *Logger
If \Current
ProcedureReturn PeekS(\Current\Message)
EndIf
EndWith
EndProcedure
Code: Alles auswählen
; ------------------------------------------------------------------------------------
; LinkedList
; Simple Linked List
; ------------------------------------------------------------------------------------
; ------------------------------------------------------------------------------------
; Strukturen
; ------------------------------------------------------------------------------------
Structure LL_Data
*Prev.LL_Data
*Next.LL_Data
*Data
EndStructure
Structure LL_Header
*Cur.LL_Data
*First.LL_Data
*Last.LL_Data
Count.i
EndStructure
; ------------------------------------------------------------------------------------
;- Erstellen, Hinzufügen, Löschen
; ------------------------------------------------------------------------------------
Procedure LL_New()
Protected *cLL.LL_Header = AllocateMemory(SizeOf(LL_Header))
ProcedureReturn *cLL
EndProcedure
Procedure LL_Add(*LL.LL_Header)
Protected *nLL.LL_Data = AllocateMemory(SizeOf(LL_Data))
If Not *LL\Cur
If *LL\First
*LL\Cur = *LL\First
ElseIf *LL\Last
*LL\Cur = *LL\Last
EndIf
EndIf
If *LL\Cur
If *LL\Cur\Next
*LL\Cur\Next\Prev = *nLL
*nLL\Next = *LL\Cur\Next
EndIf
*LL\Cur\Next = *nLL
EndIf
*nLL\Prev = *LL\Cur
If *LL\Cur = *LL\Last
*LL\Last = *nLL
EndIf
If Not *LL\First
*LL\First = *nLL
EndIf
*LL\Cur = *nLL
*LL\Count + 1
EndProcedure
Procedure LL_Delete(*LL.LL_Header)
Protected *cLL.LL_Header
If *LL\Cur
If *LL\Cur\Prev
*LL\Cur\Prev\Next = *LL\Cur\Next
EndIf
If *LL\Cur\Next
*LL\Cur\Next\Prev = *LL\Cur\Prev
EndIf
If *LL\Cur = *LL\Last
*LL\Last = *LL\Cur\Prev
EndIf
If *LL\Cur = *LL\First
*LL\First = *LL\Cur\Next
EndIf
*cLL = *LL\Cur\Prev
FreeMemory(*LL\Cur)
*LL\Cur = *cLL
*LL\Count-1
ProcedureReturn #True
EndIf
EndProcedure
Procedure LL_Free(*LL.LL_Header)
*LL\Cur = #Null
While *LL\Count
LL_Delete(*LL)
Wend
FreeMemory(*LL)
EndProcedure
Procedure LL_Count(*LL.LL_Header)
ProcedureReturn *LL\Count
EndProcedure
; ------------------------------------------------------------------------------------
;- Steuerung
; ------------------------------------------------------------------------------------
Procedure LL_Next(*LL.LL_Header)
If *LL\Cur
If *LL\Cur\Next
*LL\Cur = *LL\Cur\Next
ProcedureReturn #True
EndIf
ElseIf *LL\First
*LL\Cur = *LL\First
ProcedureReturn #True
EndIf
EndProcedure
Procedure LL_Prev(*LL.LL_Header)
If *LL\Cur
If *LL\Cur\Prev
*LL\Cur = *LL\Cur\Prev
ProcedureReturn #True
EndIf
ElseIf *LL\Last
*LL\Cur = *LL\Last
ProcedureReturn #True
EndIf
EndProcedure
Procedure LL_Reset(*LL.LL_Header)
*LL\Cur = #Null
EndProcedure
Procedure LL_First(*LL.LL_Header)
LL_Reset(*LL.LL_Header)
LL_Next(*LL.LL_Header)
EndProcedure
Procedure LL_Last(*LL.LL_Header)
LL_Reset(*LL.LL_Header)
LL_Prev(*LL.LL_Header)
EndProcedure
Procedure LL_GetEntry(*LL.LL_Header)
ProcedureReturn *LL\Cur
EndProcedure
Procedure LL_SetEntry(*LL.LL_Header, Entry)
*LL\Cur = Entry
EndProcedure
Procedure LL_SwitchNext(*LL.LL_Header)
If *LL\Cur
If *LL\Cur\Next
Swap *LL\Cur\Data, *LL\Cur\Next\Data
EndIf
EndIf
EndProcedure
Procedure LL_SwitchPrev(*LL.LL_Header)
Protected *DData
If *LL\Cur
If *LL\Cur\Prev
Swap *LL\Cur\Data, *LL\Cur\Prev\Data
EndIf
EndIf
EndProcedure
; ------------------------------------------------------------------------------------
;- Lesen & Setzen
; ------------------------------------------------------------------------------------
Procedure LL_Get(*LL.LL_Header)
If *LL\Cur
ProcedureReturn *LL\Cur\Data
EndIf
EndProcedure
Procedure LL_Set(*LL.LL_Header, Val)
If *LL\Cur
*LL\Cur\Data = Val
EndIf
EndProcedure