Button Gadget Ereignis bei Drücken UND Loslassen

Für allgemeine Fragen zur Programmierung mit PureBasic.
Chregu
Beiträge: 23
Registriert: 22.12.2018 16:07
Wohnort: Viseu de Jos, Rumänien
Kontaktdaten:

Button Gadget Ereignis bei Drücken UND Loslassen

Beitrag von Chregu »

Hallo Forum,

seit ein paar Tagen versuche ich, ein Button Gadget dazu zu kriegen, beim Drücken UND beim Loslassen ein Ereignis zu erzeugen. Konkret geht es um dieses Program:
https://www.mikrocontroller.net/attachm ... anager.zip
Im ZIP befindet sich auch der Source.
Mit dem folgenden kopierten und modifizierten Source habe ich es geschafft, auch beim Drücken den richtigen Button zu bekommen. ABER: Beim klicken ausserhalb eines Gadgets bekomme ich das letzte aktive Gadget zurück, das das den Fokus NOCH hat:

Code: Alles auswählen

If OpenWindow(0, 0, 0, 230, 90, "Event-Handling Beispiel...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  ButtonGadget  (1, 10, 10, 200, 20, "Klick mich")
  CheckBoxGadget(2, 10, 40, 200, 20, "Markiere mich")
  
  If CreateMenu(0, WindowID(0))
    MenuTitle("Menu")
    MenuItem(1, "Eintrag 1")
    MenuItem(2, "Eintrag 2")
    MenuItem(3, "Eintrag 3")
  EndIf
  
  Repeat
    Event = WaitWindowEvent()
    ;Debug event
    Select Event

      Case #PB_Event_Gadget
        Select EventGadget()
          Case 1 : Debug "Schalter 1 losgelassen!"
          Case 2 : Debug "Schalter 2 losgelassen!"
        EndSelect

      Case #PB_Event_Menu
        Select EventMenu()
          Case 1 : Debug "Menü-Eintrag 1 angeklickt!"
          Case 2 : Debug "Menü-Eintrag 2 angeklickt!"
          Case 3 : Debug "Menü-Eintrag 3 angeklickt!"
        EndSelect

      Case #WM_LBUTTONDOWN
        Debug "Schalter "+Str(GetActiveGadget())+" gedrückt!"

    EndSelect
  Until Event = #PB_Event_CloseWindow
EndIf
Gibt es eine einfache Möglichkeit, das Problem zu lösen? Die komplizierte Variante wäre, die Mauskoordinaten auszuwerten ob dort ein/das Button ist. Was ich allerdings bei der Anzahl vermeiden möchte.

Wen es interessiert: Im Tab "Weichen" möchte ich die Buttons "Rot" und "Grün" ändern, dass beim Niederdrücken der Einschaltbefehl gesendet wird und beim Loslassen der Ausschaltbefehl. Im Moment ist das fehlerhaft. Sonst muss ich eine Zeitverzögerung einbauen...

Danke und Gruss Chregu
Gruss Chregu
Benutzeravatar
Bisonte
Beiträge: 2474
Registriert: 01.04.2007 20:18

Re: Button Gadget Ereignis bei Drücken UND Loslassen

Beitrag von Bisonte »

Man nehme ein CanvasGadget, anstelle eines ButtonGadgets und schwupps, kann man das locker einzelnd handhaben.
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

Re: Button Gadget Ereignis bei Drücken UND Loslassen

Beitrag von hjbremer »

Canvasgadget und schwupps und überall lauern kleine Fallstricke.

Aber hier mal die einfache Lösung für Windows

Der Weg für Up + down war schon ok, aber nur die ersten Schritte.

Der Rest hier

Code: Alles auswählen

;geschrieben mit PB 5.70 x64 Windows 10 von HJBremer, sollte ab 5.42 funktionieren

EnableExplicit

Procedure ButtonCallback(hWnd, msg, wParam, lParam) 
   ;User definierter Callback für ButtonGadgets
   
   Protected ori = GetWindowLongPtr_(hwnd, #GWL_USERDATA)   ;Zeiger auf Original Callback
   Protected pbnr = GetDlgCtrlID_(hwnd)                     ;von welchem ButtonGadget 
   
   Select msg
      Case #WM_LBUTTONDOWN           
         PostEvent(#PB_Event_Gadget, EventWindow(), pbnr, #PB_EventType_LeftButtonDown)         
         
      Case #WM_LBUTTONUP
         PostEvent(#PB_Event_Gadget, EventWindow(), pbnr, #PB_EventType_LeftButtonUp)
         
   EndSelect
   
   ProcedureReturn CallWindowProc_(ori, hwnd, msg, wParam, lParam)   ;zurück zum Original Callback
EndProcedure 

Procedure ButtonSetCallback(pbnr) 

   Protected ori = GetWindowLongPtr_(GadgetID(pbnr), #GWL_WNDPROC)     ;Ori WindowProcPointer holen
   
   SetWindowLongPtr_(GadgetID(pbnr), #GWL_WNDPROC, @ButtonCallback())  ;WNDPROC setzen
   
   SetWindowLongPtr_(GadgetID(pbnr), #GWL_USERDATA, ori)               ;Gadget merkt sich ori
   
EndProcedure


Enumeration
   #main
   #button1
   #button2
   #checkbox1
EndEnumeration

Define event, eventtyp

If OpenWindow(#main, 0, 0, 230, 190, "Event-Handling Beispiel...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   
   ButtonGadget  (#button1, 10, 10, 200, 20, "Klick mich") : ButtonSetCallback(#button1) 
   
   CheckBoxGadget(#checkbox1, 10, 40, 200, 20, "Markiere mich")
   
   ButtonGadget  (#button2, 10, 70, 200, 20, "drück mich") : ButtonSetCallback(#button2)    
   
   If CreateMenu(0, WindowID(0))
      MenuTitle("Menu")
      MenuItem(1, "Eintrag 1")
      MenuItem(2, "Eintrag 2")
      MenuItem(3, "Eintrag 3")
   EndIf
   
   Repeat
      event = WaitWindowEvent()      
      eventtyp = EventType() 
      
      Select event            
         Case #PB_Event_Gadget

            Select EventGadget()
                  
               Case #button1
                  Select eventtyp  
                     Case #PB_EventType_LeftButtonDown
                        Debug "Button 1 #PB_EventType_LeftButtonDown"
                        
                     Case #PB_EventType_LeftButtonUp
                        Debug "Button 1 #PB_EventType_LeftButtonup"

                  EndSelect
                  
               Case #button2
                  Select eventtyp  
                     Case #PB_EventType_LeftButtonDown
                        Debug "Button 2 #PB_EventType_LeftButtonDown"

                     Case #PB_EventType_LeftButtonUp
                        Debug "Button 2 #PB_EventType_LeftButtonup"

                  EndSelect
                  
               Case #checkbox1 : Debug "CheckBoxGadget"                  
                  
            EndSelect
            
         Case #PB_Event_Menu
            Select EventMenu()
               Case 1 : Debug "Menü-Eintrag 1 angeklickt!"
               Case 2 : Debug "Menü-Eintrag 2 angeklickt!"
               Case 3 : Debug "Menü-Eintrag 3 angeklickt!"
            EndSelect
            
      EndSelect
   Until Event = #PB_Event_CloseWindow
EndIf
Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Chregu
Beiträge: 23
Registriert: 22.12.2018 16:07
Wohnort: Viseu de Jos, Rumänien
Kontaktdaten:

[Gelöst] Button Gadget Ereignis bei Drücken UND Loslassen

Beitrag von Chregu »

hjbremer hat geschrieben:Canvasgadget und schwupps und überall lauern kleine Fallstricke.
Ja genau das habe ich mir auch gedacht, nachdem ich die Doku dazu durchgelesen habe. Und wollte schon zu der Koordinaten-Variante rüber. Doch
hjbremer hat geschrieben:Aber hier mal die einfache Lösung für Windows
funktioniert! Werde das so bei mir umsetzen! Vielen Dank!

Gruss Chregu
Gruss Chregu
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

Re: Button Gadget Ereignis bei Drücken UND Loslassen

Beitrag von hjbremer »

Und hier mal eine kleine Demo fürs CanvasGadget (fehlen noch kleinere wichtige Prozeduren, wenn man sie denn braucht)

das gibt natürlich freie Auswahl was Design und Möglichkeiten angeht, ist aber umfangreicher.
und gerade am Anfang etwas schwieriger die Befehle und deren Hilfe zu nutzen :mrgreen: :mrgreen:

Code: Alles auswählen

; Demo für eigene Buttons

;Erweiterungen: z.B. SetColor, SetFont, Freegadget, Resize, SetData, abgerundete Ecken etc

DeclareModule EventButton
   
   Declare.i EventButton(pbnr, x, y, width, height, text$="", flag=0)
   
   Declare.i EventButton_SetText(pbnr, text$, textsize.d=0)
   
   Declare.i EventButton_GetState(pbnr)
   
EndDeclareModule

Module EventButton
   
   EnableExplicit
   
   Structure eventbutton
      pbnr.i
      width.i
      height.i
      colortext.i
      colorback.i
      colorpress.i
      toggle.i
      press.i
      state.i
      text.s
      textsize.d
      textfont.i
      mydata.i
   EndStructure
   
   Global default_textfont = LoadFont(#PB_Any, "Consolas", 10)
   Global default_textsize = 18
   Global default_colortext = #Black
   Global default_colorback = $3F4CDC  ;#Red
   Global default_colorpress = $5FA11A ;#Green
   
   
   Procedure.i EventButton_Draw(*mb.eventbutton) 
      Protected a = $FF000000    ;Alphawert von color wird mit Farbwert kombiniert via a|color
      Protected x, y, h, color
      
      Protected ab = 3, ab2 = ab+ab, width = *mb\width-ab2, height = *mb\height-ab2
      
      With *mb
         StartVectorDrawing(CanvasVectorOutput(\pbnr))
            
            ;Canvas Rahmen
            AddPathBox(0, 0, \width, \height): VectorSourceColor(a|#Gray): StrokePath(3)  
            
            ;Canvas Background
            color = \colorback
            If \press Or \state : color = \colorpress : EndIf
            AddPathBox(ab, ab, width, height): VectorSourceColor(a|color): FillPath() 
            
            ;draw Text
            If Len(\text)
               VectorFont(FontID(\textfont), \textsize)
               
               h = VectorParagraphHeight(\text, width, height)
               x = ab
               y = \height/2 - h/2 
               
               MovePathCursor(x, y): VectorSourceColor(a | \colortext)
               DrawVectorParagraph(\text, width, h, #PB_VectorParagraph_Center)
            EndIf
            
         StopVectorDrawing()
      EndWith
      
   EndProcedure   
   
   Procedure.i EventButton_Event()   
      Protected pbnr = EventGadget()
      Protected event = EventType()
      Protected *mb.eventbutton = GetGadgetData(pbnr)
      
      Select event
         Case #PB_EventType_LeftButtonUp
            *mb\press = 0
            
            If *mb\toggle = 0
               *mb\state = 0
            EndIf
            
            EventButton_Draw(*mb) 
            
         Case #PB_EventType_LeftButtonDown
            *mb\press = 1
            
            If *mb\toggle = 0
               *mb\state = 1
            Else
               *mb\state ! 1  ;mit XOR state ändern 
            EndIf
            
            EventButton_Draw(*mb)
      EndSelect
      
   EndProcedure
   
   Procedure.i EventButton_GetState(pbnr)
      Protected *mb.eventbutton = GetGadgetData(pbnr)
      
      ProcedureReturn *mb\state
      
   EndProcedure
   
   
   Procedure.i EventButton_SetText(pbnr, text$, textsize.d=0)
      Protected *mb.eventbutton = GetGadgetData(pbnr)
      
      *mb\text = text$
      If textsize : *mb\textsize = textsize : EndIf
      
      EventButton_Draw(*mb) 
      
   EndProcedure
   
   
   Procedure.i EventButton(pbnr, x, y, width, height, text$="", flag=0)
      ;flag hier nur #PB_Button_Toggle   
      
      Protected id, *mb.eventbutton = AllocateStructure(eventbutton)
      
      id = CanvasGadget(pbnr, x, y, width, height)
      If pbnr = #PB_Any : pbnr = id : EndIf 
      
      SetGadgetAttribute(pbnr, #PB_Canvas_Cursor, #PB_Cursor_Hand)   
      BindGadgetEvent(pbnr, @EventButton_Event(), #PB_EventType_LeftButtonUp)
      BindGadgetEvent(pbnr, @EventButton_Event(), #PB_EventType_LeftButtonDown)
      
      With *mb
         \pbnr = pbnr
         \width = width
         \height = height
         \text = text$
         \toggle = flag
         \textsize = default_textsize
         \textfont = default_textfont
         \colortext = default_colortext
         \colorback = default_colorback
         \colorpress = default_colorpress
      EndWith
      
      SetGadgetData(pbnr, *mb)   
      EventButton_Draw(*mb) 
      
      ProcedureReturn id
   EndProcedure
   
EndModule

UseModule EventButton

Enumeration
   #button1
   #button2
   #button3
EndEnumeration

Define event, eventtyp

OpenWindow(0, 0, 0, 820, 420, "Canvas example", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

EventButton(#button1, 11, 10, 110, 60, "Toggle Button", #PB_Button_Toggle) 
EventButton(#button2, 11, 100, 110, 40, "Hallo") 
EventButton(#button3, 11, 150, 110, 30, "") 

EventButton_SetText(#button3, "Button 3", 9)

Repeat
   event = WaitWindowEvent()
   eventtyp = EventType()
   
   If event = #PB_Event_Gadget
      
      Select EventGadget()                
            
         Case #button1      
            Select eventtyp      ;diese EventType() Abfrage muß beim CanvasGadget immer sein !!!!
               Case #PB_EventType_LeftButtonDown 
                  Debug "#button1 Down"
                  
               Case #PB_EventType_LeftButtonUp
                  Debug "#button1 up"                  
                  
            EndSelect
            
         Case #button2
            If eventtyp = #PB_EventType_LeftButtonDown
               Debug "#button2 down"
            EndIf
            If eventtyp = #PB_EventType_LeftButtonUp
               nr + 1
               EventButton_SetText(#button1, "ok " + nr, 25)
               Debug "#button2 up"
            EndIf
            
         Case #button3
            If eventtyp = #PB_EventType_LeftButtonDown
               Debug "state #button1 ist " + EventButton_GetState(#button1)
            EndIf
            
      EndSelect
   EndIf
   
Until Event = #PB_Event_CloseWindow
Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Antworten