Masterhook / Eventhandling wie in .Net

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

Rone

Betreff: Masterhook / Eventhandling wie in .Net

BeitragSo, Aug 13, 2006 12:50
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,

ich hab mir neulich mal dieses Masterhook sample angeschaut(hier), wobei mich dabei irgedwie störte, dass dass bei jedem Event eine Liste mit allen Gadgets durlaufen wird, nur um zu checken welches Gadget das Event ausgelöst hat. Dabei steht das gesuchte Gadget sowieso schon in 'Event.Source'....Auch sonst finde ich es ziemlich unpraktisch für jedes Gadget einen eigen Typ zu machen, zumindest in dieser form...
Nunja, als ich dann 'TGAdget' um ein Funktionspointer-Attribut erweitern wollte, sah ich das so ein Attribut schon vorhanden ist....

Mein abgeänderter MasterHook:
Code: [AUSKLAPPEN]

Rem
Rone's MAsterHook:

Damit functioniert muss TTimer (Source Code/brl.mod/timer.mod/timer.bmx) um folgendes ergänzt werden:

   Field   eventfilter(event:TEvent,context:Object)
   Field   context:Object
   
   Method SetFilter(callback(event:TEvent,context:Object),user:Object)
      eventfilter=callback
      context=user
   End Method

End Rem


SuperStrict

'##########################################

Type TMasterEventHook

   Function InstallMasterHook()
      AddHook EmitEventHook,TMasterEventHook.ProcessEvents
   End Function
   
   Function ProcessEvents:Object(iId:Int,tData:Object,tContext:Object)
      If tData=Null Then Return Null     
      Local tEv:TEvent = TEvent(tData), g:TGadget , t:TTimer
      
      If tEv.Id = EVENT_TIMERTICK Then
         t = TTimer(tEv.Source)
         If t And t.eventfilter Then
            t.eventfilter(tEv , Null)
            Return Null
         EndIf
      Else
         g = TGAdget(tEv.Source)
         If g And g.eventfilter Then
            g.eventfilter(tEv,Null)
            Return Null
         EndIf
      EndIf
      
      Return tData
   End Function
   
End Type

'############################

Type TTestApp
   
   Global handle   :TTestApp
   
   Field gSync      :TTimer
   Field gWin1      :TGadget
   Field gBut1      :TGadget
   Field gBut2      :TGadget
   Field gBut3      :TGadget
   Field gCanvas   :TGAdget
   Field label      :TGAdget
   
   Field font      :TGuiFont
   Field backColor   :Int[] = [ 0 , 0 , 0 ]
   Field zColor   :Int[] = [ 255 , 255 , 255 ]

   Method Create:TTestApp()
      gWin1= CreateWindow("SuperHook!!" , 500 , 100 , 300 , 400 , Null , WINDOW_TITLEBAR  | WINDOW_CLIENTCOORDS)
      gWin1.SetFilter(gWin1_OnEvent , Null)
      
      gBut1 = CreateButton("Back Color" , 0 , 300 , 80 , 25 , gWin1)
      gBut1.SetFilter(gBut1_OnEvent , Null)
      
      gBut2 = CreateButton("Zeiger Color" , 0 , 333 , 80 , 25 , gWin1)
      gBut2.SetFilter(gBut2_OnEvent , Null)
      
      gBut3 = CreateButton("Slect Font" , 0 , 366 , 80 , 25 , gWin1)
      gBut3.SetFilter(gBut3_OnEvent , Null)
      
      gCanvas  = CreateCanvas ( 0 , 0 , 300 , 300 , gWin1)
      gCanvas.SetFilter(gCanvas_OnEvent , Null)
      
      gSync = CreateTimer(60)
      gSync.SetFilter(gSync_OnEvent , Null)
      
      label = CreateLabel("Bla" , 100 , 350 , 100 , 30 , gWin1)
      
      handle = Self
      Return Self
   End Method
   
   Function gWin1_OnEvent:Int(tEv:TEvent , context:Object)
      Select tEv.Id
         Case EVENT_WINDOWCLOSE
            End
      End Select
   End Function

   Function gBut1_OnEvent(tEv:TEvent,context:Object)
      If RequestColor(handle.backColor[0],handle.backColor[1],handle.backColor[2])
         handle.backColor[0]=RequestedRed()
         handle.backColor[1]=RequestedGreen()
         handle.backColor[2]=RequestedBlue()
      EndIf
   End Function
   
   Function gBut2_OnEvent(tEv:TEvent,context:Object)
      If RequestColor(handle.zColor[0],handle.zColor[1],handle.zColor[2])
         handle.zColor[0]=RequestedRed()
         handle.zColor[1]=RequestedGreen()
         handle.zColor[2]=RequestedBlue()
      EndIf
   End Function
   
   Function gBut3_OnEvent(tEv:TEvent,context:Object)
      handle.font=RequestFont(handle.font)
      If handle.font
         SetGadgetFont handle.label,handle.font
         SetGadgetText handle.label,FontName(handle.font)+":"+FontSize(handle.font)
      EndIf
   End Function
   
   Function gCanvas_OnEvent(tEv:TEvent , context:Object)
      Select tEv.Id
         Case EVENT_GADGETPAINT
            SetGraphics CanvasGraphics(handle.gCanvas)
            SetOrigin 150,150
            SetClsColor handle.backColor[0],handle.backColor[1],handle.backColor[2]
            Cls
            SetLineWidth 1
            SetColor 255-handle.backColor[0],255-handle.backColor[1],255-handle.backColor[2]
            For Local i:Int = 0 To 360 Step 10
               DrawLine 0,0,140*Cos(i),140*Sin(i)   
            Next
            SetColor handle.backColor[0],handle.backColor[1],handle.backColor[2]
            DrawOval -120,-120,240,240
            SetColor handle.zColor[0] , handle.zColor[1] , handle.zColor[2]
            SetLineWidth 5
            Local t:Int=MilliSecs()
            DrawLine 0,0,120*Cos(t*0.2),120*Sin(t*0.2)
            DrawLine 0,0,80*Cos(t/360),80*Sin(t/360)
            Flip
      End Select
   End Function

   Function gSync_OnEvent(tEv:TEvent , context:Object)
      RedrawGadget handle.gCanvas
   End Function
   
End Type

'####################################

TMasterEventHook.InstallMasterHook()
Local test:TTestApp = New TTestApp.Create()

'Main loopage
Repeat
   WaitEvent
Forever

End

Bei mir bekommt jedes Gadget einfach eine OnEvent-Function auf die der Funktionspointer des Gadgets zeigt. Diese Wird dann einfach direkt über Event.Source.eventfilter(..) augerufen!

Bin mir insofern ein bisschen unsicher, dass ich 'TTimer' ergänzt habe und nicht weiss wozu der 'eventfilter' in 'TGadget' sonst noch benutzt wird, konnte allerdings nichts finden....

So, was haltet ihr davon? Gut/Schlecht/Praktisch/UnPraktisch?

mfg
  • Zuletzt bearbeitet von Rone am Mo, Feb 18, 2008 21:30, insgesamt einmal bearbeitet

Rone

BeitragMo, Feb 18, 2008 21:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Moin,

da es nun ja Reflections gibt, habe ich mein Eventhandling vor kurzen mal etwas abgeändert.
Das ganze schaut nun in etwa so aus, wie in .Net, mit einem form_designer Type, in dem ausschließlich die Gadgets erstellt und die eventhandler zugewiesen werden, sowie einem Type, in dem die Eventhandler implementiert werden.

Ich finde diese Trennung macht besonders größere Programme übersichtlicher und wartbarer....
Ein weiterer Vorteil ist, das die Eventhandler nun Methoden sind, wodurch man sich ein globales Handle sparen kann:

main.bmx:
Code: [AUSKLAPPEN]
SuperStrict

Framework brl.Basic
Import brl.maxgui
?Win32
   Import brl.win32maxgui
?MacOS
   Import brl.cocoamaxgui
?Linux
   Import brl.fltkmaxgui
?
Import brl.event
Import brl.eventqueue
Import brl.reflection
Import brl.max2d
Import brl.d3d7max2d
Import brl.glmax2d
Import brl.pngloader
Import brl.retro
Import brl.Timer

Include "eventhandling.bmx"
Include "dialog.bmx"

Global masterhook:TMasterEventHook = New TMasterEventHook
Global mainDlg:TMainDlg = New TMainDlg
mainDlg.InitializeComponent()

Repeat
   WaitEvent
Forever
End



dialog.bmx:
Code: [AUSKLAPPEN]

Type TMainDesigner

   '#Region gadgets
   Field Window   :TGadget
   Field cmdBli   :TGadget
   Field cmdBla   :TGadget
   Field cmdBlub   :TGadget
   Field panel      :TGadget   

   Method Window_OnClose(event:TEvent)    Abstract
   Method Window_OnResize(event:TEvent)    Abstract
   Method Form1_Load(event:TEvent)       Abstract
   Method cmdBli_click(event:TEvent)         Abstract
   Method cmdBla_click(event:TEvent)         Abstract
   Method cmdBlub_click(event:TEvent)         Abstract
   Method panel1_mousemove(event:TEvent)   Abstract
   Method panel1_mouseUp(event:TEvent)      Abstract
   '#End Region
   
   Method InitializeComponent(parent:TGadget=Null)
      
      Window= CreateWindow("Test" , 250 , 250 , 250 , 250 , Null , 15 )
      Local WindowEventHandler:TEventHandler = New TEventHandler
      WindowEventHandler.AddEventHandler(EVENT_WINDOWCLOSE,Self,"Window_OnClose")
      WindowEventHandler.AddEventHandler(EVENT_WINDOWSIZE,Self,"Window_OnResize")
      Window.context = WindowEventHandler
      
      cmdBli = CreateButton("Bli",0,0,100,25,Window)
      Local cmdBliEventHandler:TEventHandler = New TEventHandler
      cmdBliEventHandler.AddEventHandler(EVENT_GADGETACTION,Self,"cmdBli_Click")
      cmdBli.context = cmdBliEventHandler
      
      cmdBla = CreateButton("Bla",0,25,100,25,Window)
      Local cmdBlaEventHandler:TEventHandler = New TEventHandler
      cmdBlaEventHandler.AddEventHandler(EVENT_GADGETACTION,Self,"cmdBla_Click")
      cmdBla.context = cmdBlaEventHandler
      
      cmdBlub = CreateButton("Blub",0,50,100,25,Window)
      Local cmdBlubEventHandler:TEventHandler = New TEventHandler
      cmdBlubEventHandler.AddEventHandler(EVENT_GADGETACTION,Self,"cmdBlub_Click")
      cmdBlub.context = cmdBlubEventHandler
      
      panel = CreatePanel(100,0, 150, 250 ,Window, PANEL_ACTIVE)
      SetPanelColor panel,255,255,255
      Local panelEventHandler:TEventHandler = New TEventHandler
      panelEventHandler.AddEventHandler(EVENT_MOUSEMOVE,Self,"panel1_mousemove")
      panelEventHandler.AddEventHandler(EVENT_MOUSEUP,Self,"panel1_mouseUp")
      panel.context = panelEventHandler      
      
      Form1_Load(Null)
      
   End Method
   
End Type

 
Type TMainDlg Extends TMainDesigner
   
   Field Xpos      :Int
   Field Ypos      :Int
   
   
   Method Form1_Load(event:TEvent)              
   End Method
   
   Method panel1_mouseUp(event:TEvent)
      Confirm(event.x +" / " + event.y )
   End Method
   
   Method panel1_mousemove(event:TEvent)
      Xpos = event.x
      Ypos = event.y
      SetStatusText( Window, xpos + " / " + ypos )
   End Method
   
   Method Window_OnResize(event:TEvent)
      Print "Size"
   End Method
   
   Method Window_OnClose(event:TEvent)
       End
   End Method
   
   Method cmdBli_click(event:TEvent)
      Confirm("Bli: " + xpos + " / " + ypos)       
   End Method
   
   Method cmdBla_click(event:TEvent)    
      Confirm("Bla: " + xpos + " / " + ypos)   
   End Method
   
   Method cmdBlub_click(event:TEvent)    
      Confirm("Blub: " + xpos + " / " + ypos)   
   End Method
   
End Type


eventhandler.bmx
Code: [AUSKLAPPEN]



Type TMethodPointer
   
   Field methodName:String
   Field contextObject:Object
   Field id:TTypeId
   Field Update:TMethod
   
   Method SetMethod( context:Object, methodName:String )
      Assert context, "TMethodPointer.SetMethod: context-Argument Null Exception!"
      Assert (methodName Or methodName<>""), "TMethodPointer.SetMethod: methodName-Argument Null Exception!"   
      Self.methodName = methodName
      contextObject = context
      id=TTypeId.ForObject( context)   
      Update=id.FindMethod( methodName )
      Assert update, "TMethodPointer.SetMethod: "+methodName+" - Method does not Exist!"      
   End Method
   
   Method Process(data:Object[])
      Update.Invoke(contextObject,data )   
   End Method
   
End Type

Type TEventHandler
   
   Field   eventhandlerMap:TMap
   
   Method New()
      eventhandlerMap = New TMap
   End Method
   
   Method Delete()
      eventhandlerMap.Clear()
   End Method
   
   Method RunEventHandler( event:TEvent )
      Local eventmethod:TMethodPointer = TMethodPointer( eventhandlerMap.ValueForKey( String(event.id) ) )
      If eventmethod Then
         eventmethod.Process([event])
      EndIf
   End Method
   
   Method  AddEventHandler( _eventID:Int , context:Object , handler:String )
      Assert context,"TEventHandler.AddEventHandler: context-Argument Null Exception!"
      Assert (handler or handler<>""),"TEventHandler.AddEventHandler: handler-Argument Null Exception!"   
      Local methodPointer:TMethodPointer = New TMethodPointer
      methodPointer.SetMethod(context, handler )    
      eventhandlerMap.Insert(   String(_eventID), methodPointer)
   End Method
   
   Method RemoveEventHandler(_eventID:String )
      eventhandlerMap.Remove( _eventID )
   End Method

End Type

Type TMasterEventHook

   Method New()
      AddHook EmitEventHook,TMasterEventHook.ProcessEvents
   End Method
   
   Function ProcessEvents:Object(iId:Int,tData:Object,tContext:Object)
      If TData=Null Then Return Null     
      Local tEv:TEvent = TEvent(TData)
      Local G:TGadget = TGadget(tEv.Source)
      If G Then
         Local handler:TEventHandler = TEventHandler(G.context)
         If handler Then handler.RunEventHandler(tEv)
      EndIf
      Return TData
   End Function
   
End Type

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group