Seite 3 von 4

Re: Variable GadgetList und variable Events ?

Verfasst: 15.11.2014 22:10
von ts-soft

Code: Alles auswählen

Procedure ClickEvent()
  a = WhatEver()
  If  a > 50
    Debug "Wirst immer älter"
  Else
    Debug "Naja, das lassen wir mal gelten"
  EndIf
  ; hier gibt es keine Rückgabewerte!
EndProcedure

OpenWindow(0, #PB_Ignore, #PB_Ignore, 640, 480, "")
BindEvent( BindGadgetEvent( BindMenuEvent( .... @ClickEvent(), ...
Selbes Prinzip, es gibt keine Rückgabewerte.

Ansonsten solltest Du Dir vor Augenhalten, die Procedure weiß welches Event ausgelöst wurde, Du
mußt da eigentlich nichts weiter wissen, ausser evtl was mit diesem Event gemacht wird.

Ein Beispiel, ohne bestimmtes im Sinn ist natürlich nicht so sinnvoll ...

Code: Alles auswählen

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow : Break
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 1
          
        Default
          Debug EventGadget()
          Debug EventType()
          ; do it
      EndSelect
  EndSelect
ForEver
Die "Herrenlosen" Gadgets Wissen was zu tun ist. Wenn verschiedene Dinge zu tun, die man durch EventType nicht unterscheiden kann, dann sind eben noch Gruppen zu bilden, also 1000 to 1500, 1501 to 2000 usw.
Ausserdem läßt sich mit GadgetType(?) noch der Type ermitteln usw., usw.

Ich schreibe mir hier nen wolf und du hast es zu begreifen :wink: , weil sonste gebe ich auf :(

Re: Variable GadgetList und variable Events ?

Verfasst: 15.11.2014 22:11
von matbal
Vera hat geschrieben:Wenn eine Event-Procedure keine Rückgabewerte hat, wieso hoffe ich dann überhaupt darauf, dass eine EventCallback-Anfrage mir ein Ergebnis liefert?Wieso bekomme ich trotzdem Ergebnisse?Und woher kommen die her? Wer oder was schickt die wann?
Eigentlich ganz einfach: Du benutzt die Prozedur nicht als CallBack, sondern du rufst sie selber auf. Daher erhältst du Rückgabewerte.

Mit BindEvent, worum es ursprünglich ging, registrierst du eine Callback-Prozedur für bestimmte Ereignisse. Dann ruft PureBasic die Callback-Prozedur selber auf, wenn das Ereignis eintritt.

BindEvent gibt es aber eben noch nicht in PB4.5. Dazu mußt du dir eine aktuellere PB-Version installieren.

Re: Variable GadgetList und variable Events ?

Verfasst: 16.11.2014 00:17
von Sicro
Ok, jetzt habe ich Vera denk ich verstanden.

Frage von Vera:

Code: Alles auswählen

Procedure ButtonHandler()
  Debug "Procedure: Button wurde geklickt"
  ProcedureReturn
EndProcedure

OpenWindow(0, 100, 100, 200, 50, "Click test", #PB_Window_SystemMenu)

ButtonGadget(0, 10, 10, 180, 30, "Click me")
BindGadgetEvent(0, @ButtonHandler())

Repeat
  Event = WaitWindowEvent()
  If Event = #PB_Event_Gadget
    Select EventGadget()
      Case 0
        ; Warum wird das ausgeführt, obwohl ich das Klick-Event beim ButtonHandler per ProcedureReturn abgebrochen habe?
        Debug "Events-Schleife: Button wurde geklickt"
    EndSelect
  EndIf
Until Event = #PB_Event_CloseWindow
Antwort:
Callbacks per Bind-Befehl können keinen Event abbrechen. Zudem laufen Bind-Callbacks und WaitWindowEvent/WindowEvent parallel, wie du oben am Code siehst.
Mit ProcedureReturn erreichst du nur, das der Code nach ProcedureReturn nicht auch ausgeführt wird, der darüber befindliche wird jedoch ausgeführt.

Die Lösung (hoffentlich):

Code: Alles auswählen

Procedure WinCallback(hWnd, uMsg, wParam, lParam)
  If uMsg = #BN_CLICKED And lParam = GadgetID(0)
    ProcedureReturn #False ; Event abbrechen
  EndIf
  ProcedureReturn #PB_ProcessPureBasicEvents ; In dem Fall eigentlich unnötig, da es nicht ausgeführt wird [edit: argh... natürlich wird das gebraucht]
EndProcedure

OpenWindow(0, 100, 100, 200, 50, "Click test", #PB_Window_SystemMenu)
SetWindowCallback(@WinCallback())
ButtonGadget(0, 10, 10, 180, 30, "Click me")

Repeat
  Event = WaitWindowEvent()
  If Event = #PB_Event_Gadget
    Select EventGadget()
      Case 0
        ; Klick-Event wurde von Callback gelöscht, daher keine Ausgabe.
        Debug "Events-Schleife: Button wurde geklickt"
    EndSelect
  EndIf
Until Event = #PB_Event_CloseWindow

Re: Variable GadgetList und variable Events ?

Verfasst: 16.11.2014 15:21
von Vera
Hallo Thomas,
wir reden aneinander vorbei. Du hast im ersten Posting ja schon gesagt, dass Du Dir das Thema nicht wirklich angeguckt hast und wahrscheinlich auch nicht meinen Versuch, Kiffis Empfehlung für mich umzusetzen, ... um das es jetzt nur noch geht.
Das bedeutet nicht, dass ein Unverstehen nicht auch auf meiner Seite liegt (was ja wahrscheinlicher ist), aber ich kann auch Deine Beispiele nicht in meinem Code ein/umsetzten.

Auch versuche ich doch nicht von einem EventLoop aus einen Wert zurückzugeben, sondern dort einen zu empfangen.
Zudem tue ich das ja auch schon im Falle eines Cases - und zwar des EventGadgets.

Das in Deiner Click-Whatever-Procedure nach erfolgreicher If-Else-Kondition nichts mehr passieren kann, ist doch auch klar ... und genau so hatte ich es ja auch gemacht. Die Rückgaben waren genau wie in Deinem Beispiel innerhalb der If-Else-Abfrage.

Ich habe auch gar kein Problem mit dem EventLoop an dieser Stelle.
Ansonsten solltest Du Dir vor Augenhalten, die Procedure weiß welches Event ausgelöst wurde, Du mußt da eigentlich nichts weiter wissen, ausser evtl was mit diesem Event gemacht wird.
Genau, das ist meine Frage an die allwissende Procedure, mir bitte klar mitzuteilen, welches Gadget einen Event ausgelöst hat, damit ich in Abhängigkeit vom Ergebnis [RückgabeWert] eine Anweisung übergeben könnte.
Die "Herrenlosen" Gadgets Wissen was zu tun ist.
:allright:
Wenn verschiedene Dinge zu tun, die man durch EventType nicht unterscheiden kann, dann sind eben noch Gruppen zu bilden, also 1000 to 1500, 1501 to 2000 usw.
Ausserdem läßt sich mit GadgetType(?) noch der Type ermitteln usw., usw.
Danke für die Erinnerung. :) An die Gruppen hätte ich erstmal nicht gedacht und bei GadgetType(?) bin ich noch gar nicht angekommen, während ich noch mit ProcedureReturn kämpfe. ... doch ich glaub, ich bin heute etwas weiter gekommen.

cheers ~ Vera

Re: Variable GadgetList und variable Events ?

Verfasst: 16.11.2014 15:36
von Vera
matbal hat geschrieben:Eigentlich ganz einfach: Du benutzt die Prozedur nicht als CallBack, sondern du rufst sie selber auf. Daher erhältst du Rückgabewerte.
Mit BindEvent, worum es ursprünglich ging, registrierst du eine Callback-Prozedur für bestimmte Ereignisse. Dann ruft PureBasic die Callback-Prozedur selber auf, wenn das Ereignis eintritt.
B :idea: ngo - danke :-)
BindEvent gibt es aber eben noch nicht in PB4.5.
Ja, genau deshalb der Versuch Kiffis Beispiel trotzdem umsetzen zu können. Der Umgang mit variable Gadgets muß ja auch vor BindEvent schon möglich gewesen sein ... aber vielleicht ja nur auf dem Weg, wie Du ihn oben gezeigt hattest.

Die PBs 5+ warten mit mir auf den reparierten Rechner.

Re: Variable GadgetList und variable Events ?

Verfasst: 16.11.2014 15:57
von Vera
Sicro hat geschrieben:Callbacks per Bind-Befehl können keinen Event abbrechen. Zudem laufen Bind-Callbacks und WaitWindowEvent/WindowEvent parallel, wie du oben am Code siehst.
Dank Dir für den nochmals deutlichen Hinweis zu Callbacks.
Ich versuche allerdings nicht einen Event abzubrechen, sondern dessen Ereignisbestätigung innerhalb der Procedure.
Das die Procedure und das normale EventLoop paralell laufen, habe ich an meinem Beispiel auch schon erkannt.

Trotzdem, werde ich beide Deiner Beispiele in etwas ungewisser Zukunft ausprobieren ... und die spezielle WinLösung dann auch dort.

Gruß ~ Vera :)

Re: Variable GadgetList und variable Events ?

Verfasst: 16.11.2014 16:18
von Vera
Ok - last but not least.

Ich habe mein Beispiel nochmals so durchgeackert und aufbereitet, dass es deutlicher zeigen kann, wo meine Schwierigkeiten liegen.

Code: Alles auswählen

EnableExplicit
#Window           = 0
#ScrollAreaGadget = 0   ; 0 bzw. 88    ; für Beispiel C bitte auf 88 stellen

Global GadgetData

; Beispiel bitte einzeln unkommentiert stellen

;; ********************* Beispiel A
;; die 10 Buttons können differenziert werden, doch da ist auch der 11te Button-0 [= Scrollareagadget]
;; obwohl dies eine EventProcedure ist, liefert ProcedureReturn Ergebnisse, 
;; was angeblich nicht möglich sein soll

Procedure ButtonEvent()
  Protected EventGadget = EventGadget()
  Protected GadgetData  = GetGadgetData(EventGadget)
  Debug "-----------"
  Debug "Procedure: Button " + Str(GadgetData)
  
  ProcedureReturn GadgetData          ; wenn kommentiert, dann erhalte ich im Event()
                                      ; keine differenzierte ButtonErkennung, sondern immer nur '0'
                                      ; also brauche ich doch dieses ProcedureReturn - der nicht?
EndProcedure



;; ********************* Beispiel B
;; da nun auch immer Button-0, den es nicht gibt, als Ergebnis im Event() erscheint,
;; hatte ich gehofft, mittels einer Prüfung die Procedure vorzeitig verlassen zu können 
;; Das scheint aber nicht zu klappen, denn weiterhin wird beim Scrollen Button-0 übermittelt, anstatt 
;; diese Meldung ins Leere laufen zu lassen und nun nur korrekt im Kontrol-Case zu erscheinen


; Procedure ButtonEvent()
;   Protected EventGadget = EventGadget()
;   Protected GadgetData  = GetGadgetData(EventGadget)
;   Debug "-----------"
;   Debug "Procedure: Button " + Str(GadgetData)
;   If GadgetData = 0
;     Debug "If... GD = " + Str(GadgetData)    ; obwohl 0 eindeutig erkannt wird, erscheint trotzdem Event():Button 0
;     ProcedureReturn  ; #False                ; bezogen auf das Event()-Ergebnis, wird die Procedure hier nicht abgebrochen
;   ElseIf GadgetData > 0
;     ProcedureReturn GadgetData
;   EndIf
; EndProcedure



;; ********************* Beispiel C
;; --> hierzu oben bitte #ScrollAreaGadget = 88 setzen <--
;; Wenn das Scrollgadget einen anderen Wert als 0 hat, dann muß Ergebnis Button-0 was anderes
;; Wenn im Fall 0, GadgetData ein anderer Wert zugewiesen wird, 
;; - dann bleibt es trotzdem bei Event(): Button 0, 
;; - außer GadgetData würde in diesem 'Ausschlußbereich' expiziet zurück gegeben werden

; Procedure ButtonEvent()
;   Protected EventGadget = EventGadget()
;   Protected GadgetData  = GetGadgetData(EventGadget)
;   Debug "-----------"
;   Debug "Procedure: Button " + Str(GadgetData)
;   If GadgetData = 0
;     Debug "If... GD = " + Str(GadgetData)    
;     GadgetData = 33
;     ProcedureReturn  ; GadgetData  ;           ; ohne GadgetData wird 0 zurückgegeben, 
;   ElseIf GadgetData > 0                       ; was vermutlich nicht 0=Button meint, sondern 0=#False
;     ProcedureReturn GadgetData
;   EndIf
; EndProcedure



OpenWindow(#Window, #PB_Ignore, #PB_Ignore, 160, 280, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
ScrollAreaGadget(#ScrollAreaGadget, 10, 10, 140, 260, 110, 410)

Define Counter
Define Button
Define newY = 10
For Counter = 0 To 9
  Button = ButtonGadget(#PB_Any, 10, newY, 100, 30, "Button " + Str(Counter + 1))
  SetGadgetData(Button, Counter + 1)
  ;  BindGadgetEvent(Button, @ButtonEvent())
  newY + 40
Next
CloseGadgetList()


Repeat
  Select WaitWindowEvent()
    Case  #PB_Event_CloseWindow
      End

    Case  #PB_Event_Gadget

      GadgetData = ButtonEvent()                 ; hier ist das PROBLEM: Button 0 gibt es nicht
      Debug "Event(): Button " + Str(GadgetData) ; 0 ist das Scrollareagadget und soll als Ergebnis
                                                 ; in der Procedure ausgefiltert werden, was halt nicht klappt

      Select EventGadget()
        Case 0 : Debug "Kontroll-Case 0"    ; wird eindeutig erkannt - das ist NICHT das Problem
                                            ; sondern ein Kontroll-Debug, ob und wann sich Gadget 0 ereignet


          ;       Case 1 ... unbekannt         ; die gibt es wegen #PB_Any nicht
                                               ; und sollen deswegen über die Procedure ermittelt werden
          ;       Debug "Button " + Str(GadgetData)   ; die bleiben also immer leer

        Case 88 : Debug "Kontroll-Case 88"    ; 
          
      EndSelect
  EndSelect

ForEver
Das Hauptdilemma liegt wohl im Benutzen eines Gadgets '0', weswegen dann nicht klar ist, ob der Debug das Gadget(0) anzeigt oder den #False Wert. Beispiel C macht das dann offensichtlich, wie auch, dass die Procedure im Fall 0 immer vorzeitig verlassen wird.

Da ich in jedem Fall von der Procedure einen Wert erhalte, das kann ich wohl nicht verhindern (abfangen), bleibt mir nichts, als das dann doch im EventLoop zu erreichen.
Das versuche ich dann als nächstes ...

Dank an Alle für die viele Unterstützung :) ~ Vera

Re: Variable GadgetList und variable Events ?

Verfasst: 16.11.2014 16:51
von ts-soft
Warum Du Button und kein Array nutzt, ist mir zwar nicht klar, aber es geht auch so:

Code: Alles auswählen

EnableExplicit
#Window           = 0
#ScrollAreaGadget = 0   ; 0 bzw. 88    ; für Beispiel C bitte auf 88 stellen

OpenWindow(#Window, #PB_Ignore, #PB_Ignore, 160, 280, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
ScrollAreaGadget(#ScrollAreaGadget, 10, 10, 140, 260, 110, 410)

Define Counter
Define Button
Define newY = 10

For Counter = 0 To 9
  Button = ButtonGadget(#PB_Any, 10, newY, 100, 30, "Button " + Str(Counter + 1))
  SetGadgetData(Button, Counter + 1)
  newY + 40
Next
CloseGadgetList()

Repeat
  Select WaitWindowEvent()
    Case  #PB_Event_CloseWindow
      End

    Case  #PB_Event_Gadget
      Select EventGadget()
        Case 0 ; ScrollArea
        Case 88 : Debug "Kontroll-Case 88"
        Default
          Debug "Event(): Button " + Str(GetGadgetData(EventGadget()))
      EndSelect
  EndSelect

ForEver 
Ist es das, was Du willst?

Re: Variable GadgetList und variable Events ?

Verfasst: 16.11.2014 23:05
von Sicro
Vera hat geschrieben:

Code: Alles auswählen

;; obwohl dies eine EventProcedure ist, liefert ProcedureReturn Ergebnisse,
;; was angeblich nicht möglich sein soll
In dem Fall ist es eine ganz normale Procedure und keine EventProcedure, daher liefert diese immer Rückgabewerte (standardmäßig den Wert Null).
Eine EventProcedure/EventHandler ist eine Procedure, die per Bind-Befehl an ein Window/Gadget gebunden wird und diese liefern kein Rückgabewert.

Code: Alles auswählen

BindGadgetEvent(Gadget, @EventProcedure())
Wenn du diesen Code oben ansiehst, wird es dir klar werden, dass es nicht möglich ist, an einen Rückgabewert der EventProcedure() ranzukommen.

Wenn einem Gadget kein GadgetData zugewiesen wurde, erhältst du mit GetGadgetData() immer den Wert Null.

Vorschlag (Änderungen mit Rautezeichen gekennzeichnet):

Code: Alles auswählen

EnableExplicit
#Window           = 0
#ScrollAreaGadget = 0   ; 0 bzw. 88    ; für Beispiel C bitte auf 88 stellen

Global GadgetData

; Beispiel bitte einzeln unkommentiert stellen

;; ********************* Beispiel A
;; die 10 Buttons können differenziert werden, doch da ist auch der 11te Button-0 [= Scrollareagadget]
;; obwohl dies eine EventProcedure ist, liefert ProcedureReturn Ergebnisse,
;; was angeblich nicht möglich sein soll

Procedure ButtonEvent()
  Protected EventGadget = EventGadget()
  Protected GadgetData  = GetGadgetData(EventGadget)
  Debug "-----------"
  Debug "Procedure: Button " + Str(GadgetData)
  
  ; ############################################
  If GadgetData = 0
    GadgetData = -1
  EndIf
  ; #############################################
 
  ProcedureReturn GadgetData          ; wenn kommentiert, dann erhalte ich im Event()
                                      ; keine differenzierte ButtonErkennung, sondern immer nur '0'
                                      ; also brauche ich doch dieses ProcedureReturn - der nicht?
EndProcedure

OpenWindow(#Window, #PB_Ignore, #PB_Ignore, 160, 280, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
ScrollAreaGadget(#ScrollAreaGadget, 10, 10, 140, 260, 110, 410)

Define Counter
Define Button
Define newY = 10
For Counter = 0 To 9
  Button = ButtonGadget(#PB_Any, 10, newY, 100, 30, "Button " + Str(Counter + 1))
  SetGadgetData(Button, Counter + 1)
  ;  BindGadgetEvent(Button, @ButtonEvent())
  newY + 40
Next
CloseGadgetList()

Repeat
  Select WaitWindowEvent()
    Case  #PB_Event_CloseWindow
      End

    Case  #PB_Event_Gadget

      GadgetData = ButtonEvent()                 ; hier ist das PROBLEM: Button 0 gibt es nicht
      ; ############################################
      If GadgetData <> -1
        Debug "Event(): Button " + Str(GadgetData) ; 0 ist das Scrollareagadget und soll als Ergebnis
      EndIf
      ; ############################################
                                                 ; in der Procedure ausgefiltert werden, was halt nicht klappt

      Select EventGadget()
        Case 0 : Debug "Kontroll-Case 0"    ; wird eindeutig erkannt - das ist NICHT das Problem
                                            ; sondern ein Kontroll-Debug, ob und wann sich Gadget 0 ereignet


          ;       Case 1 ... unbekannt         ; die gibt es wegen #PB_Any nicht
                                               ; und sollen deswegen über die Procedure ermittelt werden
          ;       Debug "Button " + Str(GadgetData)   ; die bleiben also immer leer

        Case 88 : Debug "Kontroll-Case 88"    ;
         
      EndSelect
  EndSelect

ForEver

Re: Variable GadgetList und variable Events ?

Verfasst: 17.11.2014 21:42
von Vera
ts-soft hat geschrieben:Warum Du Button und kein Array nutzt, ist mir zwar nicht klar, aber es geht auch so:
Danke nochmals, :-)
das entspricht den Lösungsvarianten, die matbal oben in 3 Variationen (Array, List, Map) gepostet hatte, wovon ich eine tendenziell verwenden würde.

Doch ich wollte auch gerne meine Schwierigkeiten mit der Procedure und dessen Return lösen ... und hab wirklich viel dadurch erfahren.

Ich möchte gerne einen einfachen Launcher erstellen, der als Oberfläche eine Buttonleiste anbietet. Die Zielpfade sollen aus einer editierbaren ini Datei eingelesen werden. Die Anzahl der Pfade und somit Buttons sollte frei variierbar sein und die Buttons auf jeden Fall dann eindeutig beschriftet und den dazugehörigen Pfad aufrufen können.
Wie ich diese Infos am Besten einlese / speicher / verwalte / den Buttons zuordne weiss ich selbst noch nicht, denn ich weiss noch nicht welche Methode dafür am geeignetsten wäre. LinkedList wär mein erster Ansatz, doch einem guten Tip folge ich auch gerne.



Dank Dir auch Sirco - da schließen sich nochmals einige Wissenslücken bei mir :-)
Auch GetGadgetData(), was ich ja nur 'übernommen' habe, hatte ich mir noch garnicht gezielt angesehen. Das kommt als nächstes, um zu sehen, ob/wie das für mein LauncherProjekt zu nutzen wäre.

Deine Lösung gefällt mir gut, auch da es mir scheinbar die Option offen hält, die ButtonEvents entweder in der Procedure oder im Eventloop weiter zu verwenden. Mit der Tendenz zur Procedure, um den Eventloop nicht zu überladen.

Viele Grüße ~ Vera