Code: Alles auswählen
;-{ Definition von Macros, die verwendet werden
Macro false : 0 : EndMacro
Macro true : 1 : EndMacro
Macro nil : 0 : EndMacro
Macro null : 0 : EndMacro
Macro Is(expression)
( false Or (expression) )
EndMacro
;}
;-{ EventArg (für den *e - Parameter)
;/ Diese Struktur dient dazu, wenn Default-Argumente für Events
;/ definiert werden sollen. Bis jetzt war dies nicht nötig.
;/ (bitte bei Veröffendlichten Projekten mit dieser Lib nicht diese
;/ Struktur verändern !!! - dies führt zu Komplikationen)
Structure EventArgAtom
EndStructure
;# <description>
;# Gibt die Struktur des Event-Argument zurück.
;# </description>
;# <param name="EventArgName" type="identifier">
;# Der Name des Event-Argument.
;# </param>
;# <return type="identifier<structure>">
;# Die Struktur des Event-Argument.
;# </return>
Macro eArg(EventArgName)
EventArg_#EventArgName
EndMacro
;# <description>
;# Definiert ein neues Event-Argument.
;# </description>
;# <param name="EventArgName" type="identifier">
;# Der Name des neuen Event-Attributes.
;# </param>
;# <param name="m_Extends" type="identifier">
;# Name des EventArgument, von dem die Argumente "geerbt" werden.
;# </param>
Macro EventArg(EventArgName, m_Extends = EventArgAtom)
CompilerIf Defined(eArg(EventArgName), #PB_Structure) = 0
Structure eArg(EventArgName) Extends m_Extends
EndMacro
Macro EndEventArg
EndStructure
CompilerEndIf
EndMacro
;}
;-{ Event
;/ die Event-Call-Funktion
Prototype Event_Callback(*sender, *e)
;/ Ein Element aus der Liste der Call-Funktionen
Structure EventItem
;// Listen-Verknüpfung
*Prev.EventItem ;/ das vorherige Element
*Next.EventItem ;/ das nächste Element
;// Listen-Inhalt
Call.Event_Callback ;/ die Call-Funktion dieses Elementes
EndStructure
;/ Die Event-Struktur, die pro Event abgespeichert wird
Structure Event
;/ für Debug-Zwecke ist es hier, wenn gewollt, möglich, den Namen des Eventes abzulegen
CompilerIf #PB_Compiler_Debugger
EventName.s
CompilerEndIf
*list.EventItem ;/ Die Liste der Call-Funktionen
EndStructure
;# <description>
;# Erstellt eine neue Event-Liste.
;# </description>
Macro NewEvent()
AllocateMemory(SizeOf(Event))
EndMacro
Procedure.l NextEventCall(*event.Event) ;/ springt (wenn möglich) zum nächsten Element der Liste
If *event\list\Next
*event\list = *event\list\Next
ProcedureReturn true
EndIf
EndProcedure
Procedure.l PreviousEventCall(*event.Event) ;/ springt (wenn möglich) zum vorherigen Element der Liste
If *event\list\Prev
*event\list = *event\list\Prev
ProcedureReturn true
EndIf
EndProcedure
Procedure.l FirstEventCall(*event.Event) ;/ springt (wenn möglich) zum ersten Element der Liste
If *event\list
While PreviousEventCall(*event)
Wend
ProcedureReturn true
EndIf
EndProcedure
Procedure.l LastEventCall(*event.Event) ;/ springt (wenn möglich) zum letzten Element der Liste
If *event\list
While NextEventCall(*event)
Wend
ProcedureReturn true
EndIf
EndProcedure
Procedure AddEventCall(*event.Event, *call.Event_Callback) ;/ fügt eine neue Call-Funktion zur Event-Liste hinzu
If *event
;/ erstelle neues Listen-Element
Protected *newItem.EventItem = AllocateMemory(SizeOf(EventItem))
*newItem\Call = *call
;/ verknüpfe Listen-Element
If *event\list <> null
If *event\list\Next
*newItem\Next = *event\list\Next
*event\list\Next\Prev = *newItem
EndIf
*newItem\Prev = *event\list
*event\list\Next = *newItem
EndIf
;/ setzte das neue Listen-Elemet als aktuelles
*event\list = *newItem
EndIf
EndProcedure
Procedure DeleteEventCall(*event.Event) ;/ entfernt die akturelle Call-Funktion der Event-Liste
If *event And *event\list
Protected *tmpItem.EventItem = *event\list
If *event\list\Next
If *event\list\Prev
;/ verfollständige Verknüpfung
*event\list\Next\Prev = *event\list\Prev
*event\list\Prev\Next = *event\list\Next
;/ setzte neues aktuelles Element
*event\list = *event\list\Prev
Else
;/ verfollständige Verknüpfung
*event\list\Next\Prev = null
;/ setzte neues aktuelles Element
*event\list = *event\list\Next
EndIf
ElseIf *event\list\Prev
;/ verfollständige Verknüpfung
*event\list\Prev\Next = null
;/ setzte neues aktuelles Element
*event\list = *event\list\Prev
Else
;/ setzte neues aktuelles Element
*event\list = null
EndIf
;/ gebe das aktuelle Element frei
FreeMemory(*tmpItem)
EndIf
EndProcedure
;# <description>
;# Dient zum Durchlauf der Event-Aufrufe in der Event-Call-Liste.
;# </description>
Macro ForEach_Event(m_Event)
If m_Event And m_Event\list
FirstEventCall(m_Event)
While (m_Event\list)
EndMacro
Macro Next_Event(m_Event)
NextEventCall(m_Event)
Wend
EndIf
EndMacro
;# <description>
;# Gibt alle angegebenen Event-Aufrufe für dieses Event frei.
;# </description>
;# <param attr="(pointer)" name="event" type="Event">
;# Der Pointer des Events.
;# </param>
Procedure ClearEventCallList(*event.Event)
If *event And *event\list
;/ springe zum ersten Element der Liste
FirstEventCall(*event)
;/ durchlaufe die Liste und lösche die Call-Aufrufe
While (Not *event\list = null)
NextEventCall(*event)
FreeMemory(*event\list\Prev)
Wend
EndIf
EndProcedure
;# <description>
;# Gibt das angegebene Event wieder frei.
;# </description>
;# <param attr="(pointer)" name="event" type="Event">
;# Der Pointer des Events.
;# </param>
Macro FreeEvent(m_Event)
ClearEventCallList(m_Event)
FreeMemory(m_Event)
EndMacro
;}
;# <description>
;# Mit dieser Funktion ruft man einen Event auf (alle Call-Proceduren, die in die Liste eingeschrieben wurden).
;# </description>
;# <param attr="(pointer)" name="event" type="Event">
;# Der Pointer des Events.
;# </param>
;# <param attr="(sender)" name="sender" type="void">
;# Das Objekt, dem die Event-Liste angehört.
;# </param>
;# <param attr="(pointer)" name="e" type="EventArgAtom">
;# Der Event-Argumen-Parameter.
;# </param>
Procedure CallEvent(*event.Event, *sender, *e.EventArgAtom)
If *event And *event\list
;/ Springe zum ersten Element der Liste
While *event\list\Prev <> null
*event\list = *event\list\Prev
Wend
;/ durchlaufe die Liste des Eventes und rufe jeden Funktion auf
While *event\list
;/ rufe den Event auf
*event\list\Call(*sender, *e)
;/ nächstes Element der Liste
If *event\list\Next = null : Break : EndIf
*event\list = *event\list\Next
Wend
EndIf
EndProcedure
;-/ Default-Typen
;# <description>
;# Dies ist das Default-Event. Es wird dann verwendet, wenn keine Event-Attribute angegeben werden.
;# </description>
EventArg(Empty)
EndEventArg
Code: Alles auswählen
;{ Application
Enumeration ;#Application_Close_Reason_*
#Application_Close_Reason_Unknow = 0;/ unbekannter Schließe-Grund
#Application_Close_Reason_CloseWindow
;[...]
EndEnumeration
EventArg(Application_Close)
Reason.b ;/ der Grund, warum das Fenster beschlossen werden soll
BreakClose.b ;/ ob das Schließen des Programms abgebrochen werden soll.
EndEventArg
EventArg(Application_Closing)
Reason.b ;/ der Grund, warum das Fenster beschlossen werden soll
EndEventArg
Structure Application
*Close.Event ;*e.eArg(Application_Close) ;/ ob die Application geschlossen werden soll
*Closing.Event ;*e.eArg(Application_Closing) ;/ die Application wird geschlossen
EndStructure
;/ der lSize - Parameter ist für die "Vererbung" gedacht
Procedure NewApplication(lSize.l = SizeOf(Application))
If lSize < SizeOf(Application) : lSize = SizeOf(Application) : EndIf
Protected *this.Application = AllocateMemory(lSize)
With *this
\Close = NewEvent()
\Closing = NewEvent()
EndWith
ProcedureReturn *this
EndProcedure
Procedure FreeApplication(*this.Application)
If *this
With *this
FreeEvent(\Close)
FreeEvent(\Closing)
EndWith
FreeMemory(*this)
EndIf
EndProcedure
;}
Procedure WaitWindow(*Application.Application)
Protected lEvent.l
Protected *EventArg_Close.eArg(Application_Close)
Protected EventArg_Closing.eArg(Application_Closing)
Repeat
lEvent = WaitWindowEvent()
Select lEvent
Case #PB_Event_CloseWindow ;{
;/ definiere die Event-Argument-Struktur für Event-Aufruf vor
*EventArg_Close = AllocateMemory(SizeOf(eArg(Application_Close)))
*EventArg_Close\Reason = #Application_Close_Reason_CloseWindow
*EventArg_Close\BreakClose = false
;/ rufe ab, ob das Programm beendet werden soll
CallEvent(*Application\Close, *Application, *EventArg_Close)
;/ rufe die "Rückgabe" der Events zurück
If *EventArg_Close\BreakClose = false
EventArg_Closing\Reason = *EventArg_Close\Reason
FreeMemory(*EventArg_Close)
Break
EndIf
FreeMemory(*EventArg_Close)
;}
EndSelect
ForEver
CallEvent(*Application\Closing, *Application, @EventArg_Closing)
EndProcedure
;[...] - noch mehr Libs z.B. eine Window-Lib
Enumeration ;#Window_*
#Window_Main
EndEnumeration
Procedure Application_Close(*sender.Application, *e.eArg(Application_Close))
If *e\Reason = #Application_Close_Reason_CloseWindow
If MessageRequester("Programm beenden", "Soll das Programm wirklich beendet werden?", #PB_MessageRequester_YesNoCancel) <> #PB_MessageRequester_Yes
*e\BreakClose = true
EndIf
EndIf
EndProcedure
Procedure Application_Closing(*sender.Application, *e.eArg(Application_Closing))
CloseWindow(#Window_Main)
EndProcedure
;/ definiere Programm-Struktur
Define *MyApplication.Application = NewApplication()
AddEventCall(*MyApplication\Close, @Application_Close())
AddEventCall(*MyApplication\Closing, @Application_Closing())
;/ erstelle Fenster
OpenWindow(#Window_Main, #PB_Ignore, #PB_Ignore, 150, 100, "<title>", #PB_Window_SystemMenu)
;/ warte, bis Windows geschlossen wird (alle Aktionen sollten per Event-Handling geregelt werden)
WaitWindow(*MyApplication)
End