Beschreibung:
Angefangen hat das ganze Projekt damit, das ich ein Thread-Safe Messaging System basteln wollte, um z.B. veränderungen an Gadgets aus Thread heraus anzeigen zu können.
Da man Gadgets nur aus dem erstellenden Thread heraus behandeln soll, habe ich mir gedacht, dann mach ich mir halt eine Liste, wo einzelne Nachrichten gespeichert werden.
Diese werden z.B. in einem Child-Thread zu der Liste hinzugefügt um dann entsprechend im Main-Thread verarbeitet zu werden.
Als dieses System fertig war, hab ich mir gedach, man kann auf diesem System aufbauend auch einen FunktionsDispatcher basteln, so wie man das von anderen Sprachen her kennt.
Also habe ich angefangen die dispatcher.pbi zu schreiben, welche letztendlich eine Funktion entsprechnd in einem anderen Thread ausführen lassen kann.
z.B. eine Funktion die im 1. Fenster was vom Mainthread erstellt wurde, Gadgets neu anordnen soll auf Knopfdruck eines Gadgets aus einem Fenster das in einem Child-Thread erzeugt wurde.
Als das alles fertig war, dachte ich mir, da diese Funktionalität (in meiner Sichtweise) sehr auf ein Event-Driven System hinweist, dachte ich mir: "Fehlt ja nurnoch ein Gadget EventSystem"
Dies habe ich dann als nächstes geschrieben.
Letztendlich kann man nun mit diesen 3 Libarys wunderbar ein Event-Driven User Interface zusammen basteln. (Alla VistualStudio)
Außerdem kann dieses System auch mit mehreren Fenstern umgehen, da man dann nur ein eigenen EventMessage Loop definieren muss (ID-Technisch) und entsprechend aufrufen.
Das tolle an diesem System istaußerdem das alle Gadgets, die via EventGadget() verwaltet werden sofort benutzt werden können.
Hier der entsprechende Quellcode der einzelnen Includes und am Ende das Beispiel
multiDatatype.pbi
Code: Alles auswählen
; Multitype datatype for easy usage multiple datatypes
; like parameter for function arrays @see(threadMessaging.pbi)
; License: MIT-License
; Copyright (c) 2010 Blackskyliner
;
; Permission is hereby granted, free of charge, To any person
; obtaining a copy of this software And associated documentation
; files (the "Software"), To deal in the software without
; restriction, including without limitation the rights To use,
; copy, modify, merge, publish, distribute, sublicense, And/or sell
; copies of the software, And To permit persons To whom the
; software is furnished To do so, subject To the following
; conditions:
;
; the above copyright notice And this Permission notice shall be
; included in all copies Or substantial portions of the software.
;
; the software is PROVIDED "AS IS", without WARRANTY of any KIND,
; EXPRESS Or IMPLIED, including BUT Not LIMITED To the WARRANTIES
; of MERCHANTABILITY, FITNESS For a PARTICULAR PURPOSE And
; NONINFRINGEMENT. in NO event shall the AUTHORS Or copyright
; holders be LIABLE For any CLAIM, DAMAGES Or OTHER LIABILITY,
; WHETHER in AN ACTION of CONTRACT, TORT Or OTHERWISE, ARISING
; FROM, OUT of Or in CONNECTION With the software Or the use Or
; OTHER DEALINGS in the software.
Structure t_multiDatatype
type.l ; #PB_Integer, #PB_String, ...
StructureUnion
integer.i
long.l
double.d
float.f
quad.q
byte.b
ascii.a
character.c
word.w
unicode.u
*pointer
EndStructureUnion
string.s
EndStructure
Structure t_multiDatatypeArrayArgument
Index.t_multiDatatype[0]
EndStructure
Procedure createLongMessage(*temp.t_multiDatatype, dataVar.l)
*temp\long = dataVar
*temp\type = #PB_Long
EndProcedure
Procedure createDoubleMessage(*temp.t_multiDatatype, dataVar.d)
*temp\double = dataVar
*temp\type = #PB_Double
EndProcedure
Procedure createIntegerMessage(*temp.t_multiDatatype, dataVar.i)
*temp\integer = dataVar
*temp\type = #PB_Integer
EndProcedure
Procedure createFloatMessage(*temp.t_multiDatatype, dataVar.f)
*temp\float = dataVar
*temp\type = #PB_Float
EndProcedure
Procedure createQuadMessage(*temp.t_multiDatatype, dataVar.q)
*temp\quad = dataVar
*temp\type = #PB_Quad
EndProcedure
Procedure createAsciiMessage(*temp.t_multiDatatype, dataVar.a)
*temp\ascii = dataVar
*temp\type = #PB_Ascii
EndProcedure
Procedure createWordMessage(*temp.t_multiDatatype, dataVar.w)
*temp\word = dataVar
*temp\type = #PB_Word
EndProcedure
Procedure createCharacterMessage(*temp.t_multiDatatype, dataVar.c)
*temp\character = dataVar
*temp\type = #PB_Character
EndProcedure
Procedure createStringMessage(*temp.t_multiDatatype, dataVar.s)
*temp\string = dataVar
*temp\type = #PB_String
EndProcedure
Procedure createByteMessage(*temp.t_multiDatatype, dataVar.b)
*temp\byte = dataVar
*temp\type = #PB_Byte
EndProcedure
Procedure createPointerMessage(*temp.t_multiDatatype, *dataVar)
*temp\pointer = *dataVar
*temp\type = #PB_Function
EndProcedure
Procedure createUnicodeMessage(*temp.t_multiDatatype, dataVar.u)
*temp\unicode = dataVar
*temp\type = #PB_Unicode
EndProcedure
Code: Alles auswählen
; Memory Wrapper
; Overview over allocated data
; Needs: No dependencies
; Note:
; As of Purebasic 4.50 x86 while running a linux machine with activated Purfier
; there will be an IMA (debugger) when returning allocated memory while having a string as
; a procedure parameter. @see(http://forums.purebasic.com/german/viewtopic.php?f=20&t=22630)
; License: MIT-License
; Copyright (c) 2010 Blackskyliner
;
; Permission is hereby granted, free of charge, To any person
; obtaining a copy of this software And associated documentation
; files (the "Software"), To deal in the software without
; restriction, including without limitation the rights To use,
; copy, modify, merge, publish, distribute, sublicense, And/or sell
; copies of the software, And To permit persons To whom the
; software is furnished To do so, subject To the following
; conditions:
;
; the above copyright notice And this Permission notice shall be
; included in all copies Or substantial portions of the software.
;
; the software is PROVIDED "AS IS", without WARRANTY of any KIND,
; EXPRESS Or IMPLIED, including BUT Not LIMITED To the WARRANTIES
; of MERCHANTABILITY, FITNESS For a PARTICULAR PURPOSE And
; NONINFRINGEMENT. in NO event shall the AUTHORS Or copyright
; holders be LIABLE For any CLAIM, DAMAGES Or OTHER LIABILITY,
; WHETHER in AN ACTION of CONTRACT, TORT Or OTHERWISE, ARISING
; FROM, OUT of Or in CONNECTION With the software Or the use Or
; OTHER DEALINGS in the software.
Global _AllocatedCounter.l = 0
Global _AllocatedCounterMutex.l = CreateMutex()
Procedure _AllocateMemoryWrapper(Size.l, File.s, Line.l)
Debug File+"["+Str(Line)+"]: Memory allocated."
LockMutex(_AllocatedCounterMutex);>
_AllocatedCounter = _AllocatedCounter + 1
UnlockMutex(_AllocatedCounterMutex);<
ProcedureReturn AllocateMemory(Size)
EndProcedure
Procedure _FreeMemoryWrapper(address.i, File.s, Line.l)
Debug File+"["+Str(Line)+"]: Memory freed."
LockMutex(_AllocatedCounterMutex);>
_AllocatedCounter = _AllocatedCounter - 1
UnlockMutex(_AllocatedCounterMutex);<
FreeMemory(address)
EndProcedure
Macro AllocateMemory_(Size)
_AllocateMemoryWrapper(Size, #PB_Compiler_File, #PB_Compiler_Line)
EndMacro
Macro FreeMemory_(address)
_FreeMemoryWrapper(address, #PB_Compiler_File, #PB_Compiler_Line)
EndMacro
Macro ShowAllocatedMemoryCount()
LockMutex(_AllocatedCounterMutex);>
Debug _AllocatedCounter
UnlockMutex(_AllocatedCounterMutex);<
EndMacro
Code: Alles auswählen
; Thread Messaging Library
; Multithread-Safe
; Needs: multiDatatype.pbi
; memory.pbi
; License: MIT-License
; Copyright (c) 2010 Blackskyliner
;
; Permission is hereby granted, free of charge, To any person
; obtaining a copy of this software And associated documentation
; files (the "Software"), To deal in the software without
; restriction, including without limitation the rights To use,
; copy, modify, merge, publish, distribute, sublicense, And/or sell
; copies of the software, And To permit persons To whom the
; software is furnished To do so, subject To the following
; conditions:
;
; the above copyright notice And this Permission notice shall be
; included in all copies Or substantial portions of the software.
;
; the software is PROVIDED "AS IS", without WARRANTY of any KIND,
; EXPRESS Or IMPLIED, including BUT Not LIMITED To the WARRANTIES
; of MERCHANTABILITY, FITNESS For a PARTICULAR PURPOSE And
; NONINFRINGEMENT. in NO event shall the AUTHORS Or copyright
; holders be LIABLE For any CLAIM, DAMAGES Or OTHER LIABILITY,
; WHETHER in AN ACTION of CONTRACT, TORT Or OTHERWISE, ARISING
; FROM, OUT of Or in CONNECTION With the software Or the use Or
; OTHER DEALINGS in the software.
XIncludeFile "multiDatatype.pbi"
XIncludeFile "memory.pbi"
Structure t_message
; The Event that needs to be proccessed
; This one defines which data are in *eventData
eventCode.i
; The Data itself. (Dynamically allocated)
; You need to free them manually...
*eventData
; To differ the diffrent peek methods
; use of #PB_ Types
dataType.i
; #TRUE if it needs to be freed (autmotatically)
needToBeFreed.i
; Should it be deleted after Called?
; Manly for Eventsystems which want to register permanent callbacks
permanent.l
; So we can use GetMessage() in a while loop
; #True if called
; #False if needs to be called
wasCalled.l
EndStructure
Prototype MessageCallbackProc(*message.t_message)
Structure t_MessageCallback
*funcPointer.MessageCallbackProc
messagEventID.l
; For easy unregistering...
; Like t_message.wasCalled
wasChecked.l
EndStructure
; Global List and thread mutex
; to ensure threadsafety.
Global NewList ThreadEventMessageList.t_message()
Global ThreadEventMessageMutex.i = CreateMutex()
Global NewList ThreadEventMessageCallbackList.t_MessageCallback()
Global ThreadEventMessageCallbackMutex.i = CreateMutex()
; Inserts the given data in the event stack
Procedure CreateMessage(code.l, *eventData.l, dataType.l, dynamic.l = #True, permanent.l = #False)
Protected Index.l = -1 ; old index to restore
LockMutex(ThreadEventMessageMutex) ;>
Index = ListIndex(ThreadEventMessageList())
LastElement(ThreadEventMessageList())
AddElement(ThreadEventMessageList())
ThreadEventMessageList()\dataType = dataType;
ThreadEventMessageList()\eventCode = code;
ThreadEventMessageList()\eventData = *eventData;
ThreadEventMessageList()\needToBeFreed = dynamic
ThreadEventMessageList()\permanent = permanent
If Index <> -1
SelectElement(ThreadEventMessageList(), Index)
EndIf
UnlockMutex(ThreadEventMessageMutex) ;<
EndProcedure
; Get the top element of the event stack
Procedure GetMessages(*temp.t_message)
Protected retVar.b = #False
LockMutex(ThreadEventMessageMutex) ;>
If FirstElement(ThreadEventMessageList()) <> 0
While ThreadEventMessageList()\wasCalled
If NextElement(ThreadEventMessageList()) = 0
UnlockMutex(ThreadEventMessageMutex)
ProcedureReturn #False
EndIf
Wend
*temp\dataType = ThreadEventMessageList()\dataType
*temp\eventCode = ThreadEventMessageList()\eventCode
*temp\eventData = ThreadEventMessageList()\eventData
*temp\needToBeFreed = ThreadEventMessageList()\needToBeFreed
*temp\permanent = ThreadEventMessageList()\permanent
ThreadEventMessageList()\wasCalled = #True
retVar = #True
EndIf
UnlockMutex(ThreadEventMessageMutex) ;<
ProcedureReturn retVar
EndProcedure
Procedure DeleteMessage(*message.t_message)
;CallDebugger
If *message\needToBeFreed = #True
FreeMemory_(*message\eventData); free the dynamic data
EndIf
; The other data is automatically freed.
EndProcedure
Procedure registerMessageEventCallback(eventID.l, *callback)
LockMutex(ThreadEventMessageCallbackMutex);>
LastElement(ThreadEventMessageCallbackList())
AddElement(ThreadEventMessageCallbackList())
ThreadEventMessageCallbackList()\funcPointer = *callback
ThreadEventMessageCallbackList()\messagEventID = eventID
UnlockMutex(ThreadEventMessageCallbackMutex);<
EndProcedure
Procedure MessageEvent(eventID.l)
Protected temp.t_message
Protected calledOnce.l = #False
While GetMessages(@temp)
calledOnce = #False
LockMutex(ThreadEventMessageCallbackMutex);>
ResetList(ThreadEventMessageCallbackList())
While NextElement(ThreadEventMessageCallbackList())
If ThreadEventMessageCallbackList()\messagEventID = eventID
ThreadEventMessageCallbackList()\funcPointer(temp)
calledOnce = #True
EndIf
Wend
UnlockMutex(ThreadEventMessageCallbackMutex);<
;CallDebugger
If calledOnce And ThreadEventMessageList()\permanent = #False
LockMutex(ThreadEventMessageMutex);>
DeleteElement(ThreadEventMessageList())
UnlockMutex(ThreadEventMessageMutex);<
; Done with the Message so free the dynamically allocated message data
DeleteMessage(@temp)
EndIf
Wend
; Reset wasCalled
LockMutex(ThreadEventMessageMutex);>
ResetList(ThreadEventMessageList())
While NextElement(ThreadEventMessageList())
ThreadEventMessageList()\wasCalled = #False
Wend
UnlockMutex(ThreadEventMessageMutex);<
EndProcedure
; If #PB_Any and FuncPointer = #Null, all Callbacks will be deleted
; If only #PB_Any and FuncPointer is Valid, all Callbacks to this function will be deleted
; If eventID is specified but the FuncPointer is #Null, all Callbacks to this EventId will be deleted
Procedure unregisterMessageEventCallback(eventID.l, *callback)
Protected temp.t_message
Protected calledOnce.l = #False
LockMutex(ThreadEventMessageCallbackMutex);>
While FirstElement(ThreadEventMessageCallbackList())
While ThreadEventMessageCallbackList()\wasChecked
If NextElement(ThreadEventMessageCallbackList()) = 0
ResetList(ThreadEventMessageCallbackList())
While NextElement(ThreadEventMessageCallbackList())
ThreadEventMessageCallbackList()\wasChecked = #False
Wend
UnlockMutex(ThreadEventMessageCallbackMutex)
ProcedureReturn
EndIf
Wend
ThreadEventMessageCallbackList()\wasChecked = #True
If eventID = #PB_Any Or eventID = ThreadEventMessageCallbackList()\messagEventID
If *callback = #Null Or *callback = ThreadEventMessageCallbackList()\funcPointer
DeleteElement(ThreadEventMessageCallbackList())
EndIf
EndIf
Wend
UnlockMutex(ThreadEventMessageCallbackMutex);<
EndProcedure
Code: Alles auswählen
; Function Dispatcher Library
; Needs: threadMessaging.pbi
; License: MIT-License
; Copyright (c) 2010 Blackskyliner
;
; Permission is hereby granted, free of charge, To any person
; obtaining a copy of this software And associated documentation
; files (the "Software"), To deal in the software without
; restriction, including without limitation the rights To use,
; copy, modify, merge, publish, distribute, sublicense, And/or sell
; copies of the software, And To permit persons To whom the
; software is furnished To do so, subject To the following
; conditions:
;
; the above copyright notice And this Permission notice shall be
; included in all copies Or substantial portions of the software.
;
; the software is PROVIDED "AS IS", without WARRANTY of any KIND,
; EXPRESS Or IMPLIED, including BUT Not LIMITED To the WARRANTIES
; of MERCHANTABILITY, FITNESS For a PARTICULAR PURPOSE And
; NONINFRINGEMENT. in NO event shall the AUTHORS Or copyright
; holders be LIABLE For any CLAIM, DAMAGES Or OTHER LIABILITY,
; WHETHER in AN ACTION of CONTRACT, TORT Or OTHERWISE, ARISING
; FROM, OUT of Or in CONNECTION With the software Or the use Or
; OTHER DEALINGS in the software.
XIncludeFile "threadMessaging.pbi"
Enumeration
#Message_DispatchedFunction
#Message_CustomInternMAX
EndEnumeration
Prototype DispatchProc(Array Param.t_multiDatatype(1))
Structure t_dispatch
*func.DispatchProc
Array Param.t_multiDatatype(10)
EndStructure
Procedure dispatchProcedure(*func.DispatchProc, Array Param.t_multiDatatype(1))
Protected *temp.t_dispatch = AllocateMemory(SizeOf(t_dispatch))
InitializeStructure(*temp, t_dispatch)
*temp\func = *func;
CopyArray(Param(), *temp\Param())
CreateMessage(#Message_DispatchedFunction, *temp, #PB_Function)
EndProcedure
Procedure callDispatchedProcedure(*message.t_message)
Protected temp.t_dispatch;
If *message\dataType = #PB_Function
CopyMemory(*message\eventData, @temp, SizeOf(t_dispatch))
temp\func(temp\Param())
Else
Debug "Dispatched Datatype Error!!!"
EndIf
EndProcedure
Code: Alles auswählen
; Gadget Event Handler Library
; Needs: threadMessaging.pbi
; memory.pbi
; License: MIT-License
; Copyright (c) 2010 Blackskyliner
;
; Permission is hereby granted, free of charge, To any person
; obtaining a copy of this software And associated documentation
; files (the "Software"), To deal in the software without
; restriction, including without limitation the rights To use,
; copy, modify, merge, publish, distribute, sublicense, And/or sell
; copies of the software, And To permit persons To whom the
; software is furnished To do so, subject To the following
; conditions:
;
; the above copyright notice And this Permission notice shall be
; included in all copies Or substantial portions of the software.
;
; the software is PROVIDED "AS IS", without WARRANTY of any KIND,
; EXPRESS Or IMPLIED, including BUT Not LIMITED To the WARRANTIES
; of MERCHANTABILITY, FITNESS For a PARTICULAR PURPOSE And
; NONINFRINGEMENT. in NO event shall the AUTHORS Or copyright
; holders be LIABLE For any CLAIM, DAMAGES Or OTHER LIABILITY,
; WHETHER in AN ACTION of CONTRACT, TORT Or OTHERWISE, ARISING
; FROM, OUT of Or in CONNECTION With the software Or the use Or
; OTHER DEALINGS in the software.
XIncludeFile "threadMessaging.pbi"
XIncludeFile "memory.pbi"
#GadgetMessage = $0F
Prototype gadgetCallbackFunc(gadgetID.l, event.l)
Structure t_gadgetElement
gadgetID.l
event.l
*func.gadgetCallbackFunc
EndStructure
Procedure registerGadgetCallback(eventHandleLoop.l, gadgetID.l, event.l, *callback.gadgetCallbackFunc)
Protected *temp.t_gadgetElement = AllocateMemory_(SizeOf(t_gadgetElement))
*temp\event = event
*temp\func = *callback
*temp\gadgetID = gadgetID
CreateMessage(eventHandleLoop, *temp, #GadgetMessage, #True, #True)
EndProcedure
Procedure unregisterGadgetCallback(eventHandleLoop.l, gadgetID.l, event.l, *callback.gadgetCallbackFunc)
Protected temp.t_message
Protected temp2.t_gadgetElement
; Dirty... could lead to double executing...
LockMutex(ThreadEventMessageMutex) ;>
ResetList(ThreadEventMessageList())
While NextElement(ThreadEventMessageList())
ThreadEventMessageList()\wasCalled = #False
Wend
UnlockMutex(ThreadEventMessageMutex) ;<
; Also dity becaus use of "intern" threadMessaging functions...
While GetMessages(@temp)
If temp\eventCode = eventHandleLoop Or eventHandleLoop = #PB_Any
If temp\dataType = #GadgetMessage
CopyMemory(temp\eventData, @temp2, SizeOf(t_gadgetElement))
If temp2\event = event Or event = #PB_Any
If temp2\gadgetID = gadgetID Or gadgetID = #PB_Any
If temp2\func = *callback Or *callback = #Null
LockMutex(ThreadEventMessageMutex) ;>
DeleteElement(ThreadEventMessageList())
UnlockMutex(ThreadEventMessageMutex) ;<
DeleteMessage(@temp)
EndIf
EndIf
EndIf
EndIf
EndIf
Wend
EndProcedure
Procedure handleGadgetCallbacks(*message.t_message)
Protected temp.t_gadgetElement
Protected GadgetEventID.l = EventGadget()
CopyMemory(*message\eventData, @temp, SizeOf(t_gadgetElement))
If temp\gadgetID = GadgetEventID
If EventType() = temp\event
temp\func(temp\gadgetID, temp\event)
EndIf
EndIf
EndProcedure
Code: Alles auswählen
; Example for the usage of:
; - Thread Messaging Library
; - Function Dispatcher Library
; - Gadget Event Handler Library
; Needs: multiDatatype.pbi
; threadMessaging.pbi
; dispatcher.pbi
; gadgetEventHandler.pbi
; memory.pbi
; License: MIT-License
; Copyright (c) 2010 Blackskyliner
;
; Permission is hereby granted, free of charge, To any person
; obtaining a copy of this software And associated documentation
; files (the "Software"), To deal in the software without
; restriction, including without limitation the rights To use,
; copy, modify, merge, publish, distribute, sublicense, And/or sell
; copies of the software, And To permit persons To whom the
; software is furnished To do so, subject To the following
; conditions:
;
; the above copyright notice And this Permission notice shall be
; included in all copies Or substantial portions of the software.
;
; the software is PROVIDED "AS IS", without WARRANTY of any KIND,
; EXPRESS Or IMPLIED, including BUT Not LIMITED To the WARRANTIES
; of MERCHANTABILITY, FITNESS For a PARTICULAR PURPOSE And
; NONINFRINGEMENT. in NO event shall the AUTHORS Or copyright
; holders be LIABLE For any CLAIM, DAMAGES Or OTHER LIABILITY,
; WHETHER in AN ACTION of CONTRACT, TORT Or OTHERWISE, ARISING
; FROM, OUT of Or in CONNECTION With the software Or the use Or
; OTHER DEALINGS in the software.
EnableExplicit
XIncludeFile "memory.pbi"
XIncludeFile "multiDatatype.pbi"
XIncludeFile "threadMessaging.pbi"
XIncludeFile "dispatcher.pbi"
XIncludeFile "gadgetEventHandler.pbi"
; Custom Messages
Enumeration #Message_CustomInternMAX
#Message_AddElement
#Message_DelElement
#Message_CustomMAX
EndEnumeration
Enumeration
#EventMessageLoop_MainWindow
#GadgetEventhandleLoop
EndEnumeration
Procedure DispatchMe(Array Param.t_multiDatatype(1))
If Param(0)\type = #PB_Long
;Debug Param(0)\long
Else
; Statt Debug, OnError Libary nutzen
Debug "Invalid Type: Long expected!"
EndIf
EndProcedure
Procedure ThreadedProcedure(dummy)
Protected *eventDataBuffer;
Protected str$
Protected length.l
Protected i.l, n.l
; Dispatch a function to do whatever in the mainThread...
Dim params.t_multiDatatype(10)
createLongMessage(params(0), 1000)
dispatchProcedure(@DispatchMe(), params())
;Some test messages
For i = 0 To 1
str$ = "Das ist ein Test."
length = Len(str$)
*eventDataBuffer = AllocateMemory_((length+1)*SizeOf(str$))
PokeS(*eventDataBuffer, str$)
CreateMessage(#Message_AddElement, *eventDataBuffer, #PB_String)
str$ = "Und noch einer, weils so schön ist :P."
length = Len(str$)
; Länge + Nullbyte * Size of one character
*eventDataBuffer = AllocateMemory_((length+1)*SizeOf(str$))
PokeS(*eventDataBuffer, str$)
CreateMessage(#Message_AddElement, *eventDataBuffer, #PB_String)
CreateMessage(#Message_AddElement, @"", #PB_String, #False)
Next i
EndProcedure
; Proccess each message
Procedure MessageCallback(*message.t_message)
Select *message\eventCode
Case #Message_AddElement
If *message\dataType = #PB_String
AddGadgetItem(0,-1,PeekS(*message\eventData))
EndIf
Case #Message_DispatchedFunction
; Maybe do some stuff to stored data and then call the Proc.
callDispatchedProcedure(*message)
Default
Debug "Unknown Event..."
EndSelect
EndProcedure
CreateThread(@ThreadedProcedure(), #Null)
Procedure deleteButton_OnClick(gadgetID.l, event.l)
RemoveGadgetItem(0, GetGadgetState(0))
unregisterGadgetCallback(#GadgetEventhandleLoop, 1, #PB_EventType_LeftClick, @deleteButton_OnClick())
EndProcedure
Procedure exitButton_OnClick(gadgetID.l, event.l)
End ; Dirty, because some dynamic data will not be freed...
EndProcedure
; Register one Callback function for the EventDispatcher
; Every registered function will get the EventMessagem
; one after another. (But only those which are for their ID)
registerMessageEventCallback(#EventMessageLoop_MainWindow,@MessageCallback())
registerMessageEventCallback(#GadgetEventhandleLoop, @handleGadgetCallbacks())
OpenWindow(0,0,0,300,200,"Test App")
ListViewGadget(0,0,0,300,175)
ButtonGadget(1, 0,175,150,25, "Delete Selected")
ButtonGadget(2, 150,175,150,25, "Exit App")
registerGadgetCallback(#GadgetEventhandleLoop, 1, #PB_EventType_LeftClick, @deleteButton_OnClick())
registerGadgetCallback(#GadgetEventhandleLoop, 2, #PB_EventType_LeftClick, @exitButton_OnClick())
Define event.l
Repeat
; EventDispatcher
MessageEvent(#EventMessageLoop_MainWindow)
event = WaitWindowEvent(5)
Select event
Case #PB_Event_Gadget
MessageEvent(#GadgetEventhandleLoop)
EndSelect
Until event = #PB_Event_CloseWindow
unregisterGadgetCallback(#PB_Any, #PB_Any, #PB_Any, #Null)
unregisterMessageEventCallback(#PB_Any, #Null)
ShowAllocatedMemoryCount()
Kritik erwünscht
MFG
Blackskyliner