CheckBox doesn't support #PB_EventType_Change

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
BarryG
Addict
Addict
Posts: 4173
Joined: Thu Apr 18, 2019 8:17 am

CheckBox doesn't support #PB_EventType_Change

Post by BarryG »

Just spent over an hour trying to work out why my main app wasn't responding to a checkbox change... and discovered this. :shock:

Surely this event type should be supported for checkboxes when their state changes? Using GetGadgetState() doesn't help because I just want to know if one of MANY checkboxes has been clicked (as well as a stringgadget being changed), without iterating through all my gadgets and checking their new state compared to their old state.

Code: Select all

If OpenWindow(0, 0, 0, 270, 100, "Changed", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CheckBoxGadget(0, 10, 10, 250, 20, "CheckBox standard")
  StringGadget(1, 10, 40, 250, 20, "")
  Repeat
    ev=WaitWindowEvent()
    If ev=#PB_Event_Gadget And EventType()=#PB_EventType_Change ; Doesn't work for CheckBoxes. :(
      Debug "Either a CheckBox or StringGadget changed"
    EndIf
  Until  ev= #PB_Event_CloseWindow
EndIf
[Edit] Example of what I want to do: In the screenshot below (not my app), I just want to know if the user has changed ANY gadget shown, including the checkbox states. See how many there are, and why I don't want to save the state of every gadget to test? An event raised when any gadget changes would be fantastic and more convenient, because my main loop would know SOMETHING changed without me needing to know WHAT changed.

Image
Last edited by BarryG on Thu Nov 14, 2024 11:52 am, edited 4 times in total.
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: CheckBox doesn't support #PB_EventType_Change

Post by breeze4me »

Check by the event gadget number without the event type.
There are a few gadgets that don't have a specified event type, and it's a bit ambiguous to just check by gadget number.

Code: Select all

If OpenWindow(0, 0, 0, 270, 160, "CheckBoxGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CheckBoxGadget(0, 10,  10, 250, 20, "CheckBox standard")
  Repeat
    ev=WaitWindowEvent()
    If ev=#PB_Event_Gadget And EventGadget() = 0
      Debug "Checkbox changed"
    EndIf
  Until  ev= #PB_Event_CloseWindow
EndIf
Last edited by breeze4me on Sat Nov 09, 2024 6:52 am, edited 1 time in total.
BarryG
Addict
Addict
Posts: 4173
Joined: Thu Apr 18, 2019 8:17 am

Re: CheckBox doesn't support #PB_EventType_Change

Post by BarryG »

Edited my first post while you replied. :) That won't work because as mentioned, I don't want to iterate through and check all my gadgets. There could be an unlimited number of them as they can be created at runtime. EventType() would do the job better, as demonstrated in my edited first post (see the edited "Debug" line). I don't need to check their state, but just to know that they've been changed.
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: CheckBox doesn't support #PB_EventType_Change

Post by breeze4me »

For the time being, you can use something like this.

Code: Select all

Procedure WndProc(hwnd, msg, wparam, lparam)
  Protected Window, Gadget
  
  If msg = #WM_COMMAND And (wparam >> 16) & $FFFF = #BN_CLICKED
    Window = GetProp_(hwnd, "PB_WindowID") - 1
    If WindowID(Window) = hwnd
      Gadget = GetWindowLongPtr_(lparam, #GWLP_ID)
      If GadgetID(Gadget) = lparam
        PostEvent(#PB_Event_Gadget, Window, Gadget, #PB_EventType_Change)
      EndIf
    EndIf
  EndIf
  
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

If OpenWindow(0, 0, 0, 270, 160, "CheckBoxGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CheckBoxGadget(0, 10,  10, 250, 20, "CheckBox standard")
  CheckBoxGadget(1, 10,  40, 250, 20, "CheckBox standard")
  StringGadget(2, 10,  70, 250, 20, "")
  
  SetWindowCallback(@WndProc())
  ; Fixed an issue with an event being fired immediately after execution. Probably not happening in real app.
  While WindowEvent() : Wend
  
  Repeat
    ev=WaitWindowEvent()
    If ev=#PB_Event_Gadget And EventType() = #PB_EventType_Change
      Debug "Either a CheckBox or StringGadget changed : " + EventGadget()
    EndIf
  Until  ev= #PB_Event_CloseWindow
EndIf

Last edited by breeze4me on Sat Nov 09, 2024 7:31 am, edited 2 times in total.
User avatar
jacdelad
Addict
Addict
Posts: 2010
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: CheckBox doesn't support #PB_EventType_Change

Post by jacdelad »

Checkboxen usually work well with BindGadget if just a short piece of code has to be executed.
Can't test right now: Does it send a #PB_EventType_LeftClick?
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
BarryG
Addict
Addict
Posts: 4173
Joined: Thu Apr 18, 2019 8:17 am

Re: CheckBox doesn't support #PB_EventType_Change

Post by BarryG »

At the moment I've resorted to this (no callback and no need to test a specific gadget):

Code: Select all

If OpenWindow(0, 0, 0, 270, 100, "CheckBoxGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CheckBoxGadget(0, 10, 10, 250, 20, "CheckBox standard")
  StringGadget(1, 10, 40, 250, 20, "")
  Repeat : Until WaitWindowEvent()=0 ; Flush events before main loop starts.
  Repeat
    ev=WaitWindowEvent()
    If ev=#PB_Event_Gadget
      ag=GetActiveGadget()
      If EventType()=#PB_EventType_Change Or (ag<>-1 And GadgetType(ag)=#PB_GadgetType_CheckBox)
        Debug "CheckBox or StringGadget changed"
      EndIf
    EndIf
  Until  ev= #PB_Event_CloseWindow
EndIf
The manual says the CheckBoxGadget doesn't support ANY event types... and neither does the ButtonGadget. :shock: Both should, IMO, because the ButtonGadget has a #PB_Button_Toggle mode, so like a CheckBox it'd be good to get a change event when it's been toggled from a click.
Last edited by BarryG on Sat Nov 09, 2024 10:37 am, edited 1 time in total.
AZJIO
Addict
Addict
Posts: 2191
Joined: Sun May 14, 2017 1:48 am

Re: CheckBox doesn't support #PB_EventType_Change

Post by AZJIO »

1. When an event comes from a checkbox, it always changes.
2. If checkboxes are generated, then you can create a range of identifiers for them and check them in a cycle from 1 to the maximum.
3. It would be possible to save the state in SetGadgetData, but this is unnecessary; it is enough to check the state of the gadget without additional data caching.

Code: Select all

Define y, x, i, eg

If OpenWindow(0, 0, 0, 620, 450, "Example...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	ButtonGadget(1, 10, 10, 18, 30, Chr($205E)) ; ⁞ (menu)
	ButtonGadget(2, 30, 10, 18, 30, Chr($2261)) ; ≡ (menu)
	ButtonGadget(3, 50, 10, 26, 30, Chr($2630)) ; ☰ (menu)
	ButtonGadget(4, 78, 10, 26, 30, Chr($25BC))	; ▼ (menu)

	ButtonGadget(5, 10, 50, 26, 30, Chr($266B)) ; ♫ (melody)
	ButtonGadget(6, 78, 50, 26, 26, Chr($2026))	; … (browse)
	
	y = 80
	x = 10
	For i = 7 To 108
		CheckBoxGadget(i , x , y , 100 , 20 , Str(i))
		y + 20
		If y > 400
			y = 80
		EndIf
		If y = 80
			x + 100
		EndIf
	Next
	
	Repeat
		Select WaitWindowEvent()
			Case #PB_Event_Gadget
				eg = EventGadget()
				Select eg
					Case 7 To 108
						Debug eg
						Debug GetGadgetState(eg) & #PB_Checkbox_Checked
				EndSelect
			Case #PB_Event_CloseWindow
				CloseWindow(0)
				End
		EndSelect
	ForEver
EndIf
Last edited by AZJIO on Sat Nov 09, 2024 8:00 am, edited 1 time in total.
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Re: CheckBox doesn't support #PB_EventType_Change

Post by breeze4me »

@BarryG
Clicking the checkbox gadget while the string gadget is active fires two more events from the string gadget. And typing in the string gadget fires two events.
If this is not a problem in your app, you don't need to fix it.

Code: Select all

If OpenWindow(0, 0, 0, 270, 100, "CheckBoxGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CheckBoxGadget(0, 10, 10, 250, 20, "CheckBox standard")
  StringGadget(1, 10, 40, 250, 20, "")
  Repeat : Until WaitWindowEvent()=0 ; Flush events before main loop starts.
  Repeat
    ev=WaitWindowEvent()
    If ev=#PB_Event_Gadget
      ag=GetActiveGadget()
      If EventType()=#PB_EventType_Change Or (ag<>-1 And GadgetType(eg)=#PB_GadgetType_CheckBox)
        Debug "CheckBox or StringGadget changed " + EventGadget()
      EndIf
    EndIf
  Until  ev= #PB_Event_CloseWindow
EndIf
User avatar
mk-soft
Always Here
Always Here
Posts: 6246
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: CheckBox doesn't support #PB_EventType_Change

Post by mk-soft »

Save last state ...

Code: Select all

;-TOP

Procedure UpdateWindow()
  Protected dx, dy
  dx = WindowWidth(0)
  dy = WindowHeight(0) - StatusBarHeight(0) - MenuHeight()
  ; Resize Gadgets
EndProcedure

Procedure Main()
  Protected dx, dy
  
  #WinStyle = #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget
  
  If OpenWindow(0, #PB_Ignore, #PB_Ignore, 600, 400, "Test Window", #WinStyle)
    ; MenuBar
    CreateMenu(0, WindowID(0))
    MenuTitle("&File")
    MenuItem(99, "E&xit")
    
    ; StatusBar
    CreateStatusBar(0, WindowID(0))
    AddStatusBarField(#PB_Ignore)
    
    ; Gadgets
    dx = WindowWidth(0)
    dy = WindowHeight(0) - StatusBarHeight(0) - MenuHeight()
    CheckBoxGadget(0, 10, 10, 120, 25, "CheckBox")
    
    ; Bind Events
    BindEvent(#PB_Event_SizeWindow, @UpdateWindow(), 0)
    
    ; Main Loop
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          Select EventWindow()
            Case 0
              Break
          EndSelect
          
        Case #PB_Event_Menu
          Select EventMenu()
            Case 99
              PostEvent(#PB_Event_CloseWindow, 0, 0)
              
          EndSelect
          
        Case #PB_Event_Gadget
          Select EventGadget()
            Case 0
              Select EventType()
                Case #PB_EventType_LeftClick
                  state = GetGadgetState(0)
                  If state <> GetGadgetData(0)
                    SetGadgetData(0, state)
                    ; Do any
                    Debug "ComboBox changed"
                  EndIf
              EndSelect
              
          EndSelect
          
      EndSelect
    ForEver
    
  EndIf
  
EndProcedure : Main()
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
BarryG
Addict
Addict
Posts: 4173
Joined: Thu Apr 18, 2019 8:17 am

Re: CheckBox doesn't support #PB_EventType_Change

Post by BarryG »

Thanks for the replies and workarounds, but this is just to request that CheckBoxGadgets (and ButtonGadgets) support #PB_EventType_Change so that workarounds aren't needed. :) It's logical that any gadget that can change, should use #PB_EventType_Change when it does. To me, anyway.
AZJIO
Addict
Addict
Posts: 2191
Joined: Sun May 14, 2017 1:48 am

Re: CheckBox doesn't support #PB_EventType_Change

Post by AZJIO »

The constant #PB_EventType_Change is not just a change of any element, it is a constant existing in WinAPI for elements that support text input. If you make a universal crutch, then it can later create problems. There are a lot of WinAPI functions that are not supported, for ListIconGadget up to 150 functions instead of 10
Axolotl
Addict
Addict
Posts: 837
Joined: Wed Dec 31, 2008 3:36 pm

Re: CheckBox doesn't support #PB_EventType_Change

Post by Axolotl »

not as fancy as the others, but maybe ...

Code: Select all

; selfmade constant ..... 
;
#PB_EventType_Checked = 0 

If OpenWindow(0, 0, 0, 270, 100, "Changed", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CheckBoxGadget(0, 10, 10, 250, 20, "CheckBox standard")
  StringGadget(1, 10, 40, 250, 20, "")

  Repeat
    ev=WaitWindowEvent()
    If ev = #PB_Event_Gadget And (EventType() = #PB_EventType_Change Or EventType() = #PB_EventType_Checked) ; Doesn't work for CheckBoxes. :(
      Debug "Either a CheckBox or StringGadget changed"
    EndIf
  Until  ev= #PB_Event_CloseWindow
EndIf
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
mestnyi
Addict
Addict
Posts: 1098
Joined: Mon Nov 25, 2013 6:41 am

Re: CheckBox doesn't support #PB_EventType_Change

Post by mestnyi »

That's how it works.

Code: Select all

If OpenWindow(0, 0, 0, 270, 100, "Changed", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CheckBoxGadget(0, 10, 10, 250, 20, "CheckBox standard")
  StringGadget(1, 10, 40, 250, 20, "")
  Repeat
    ev=WaitWindowEvent()
    If ev=#PB_Event_Gadget And EventType()=0;#PB_EventType_Change ; Doesn't work for CheckBoxes. :(
      Debug "Either a CheckBox or StringGadget changed"
    EndIf
  Until  ev= #PB_Event_CloseWindow
EndIf
User avatar
mk-soft
Always Here
Always Here
Posts: 6246
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: CheckBox doesn't support #PB_EventType_Change

Post by mk-soft »

EventType() = #Null is ...

Code: Select all

Debug #PB_EventType_LeftClick
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
mestnyi
Addict
Addict
Posts: 1098
Joined: Mon Nov 25, 2013 6:41 am

Re: CheckBox doesn't support #PB_EventType_Change

Post by mestnyi »

mk-soft wrote: Sat Nov 09, 2024 11:54 pm EventType() = #Null is ...

Code: Select all

Debug #PB_EventType_LeftClick
That's true, but Fred doesn't want to fix this situation in any way. moreover, I do not understand how the event value can be zero. :D
Post Reply