Generate missing event types #PB_EventType_LostFocus and #PB_EventType_Focus

Share your advanced PureBasic knowledge/code with the community.
Little John
Addict
Addict
Posts: 4775
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Generate missing event types #PB_EventType_LostFocus and #PB_EventType_Focus

Post by Little John »

Press the [TAB] key ...

Code: Select all

; <https://www.purebasic.fr/english/viewtopic.php?t=86619>
; tested with PB 6.20 (x64) on Windows 11

EnableExplicit


Procedure GenerateFocusEvents()
   ; -- This is needed because some gadgets do not natively support EventType() #PB_EventType_LostFocus and #PB_EventType_Focus.
   Static prevGadget.i=-1
   Protected curGadget.i
   
   curGadget = GetActiveGadget()   ; -1, if no gadget has the focus
   If prevGadget <> curGadget
      If IsGadget(prevGadget)
         Select GadgetType(prevGadget)
            Case #PB_GadgetType_CheckBox, #PB_GadgetType_ComboBox, #PB_GadgetType_ListIcon, #PB_GadgetType_Spin, #PB_GadgetType_Button
               PostEvent(#PB_Event_Gadget, EventWindow(), prevGadget, #PB_EventType_LostFocus)
         EndSelect
      EndIf
      
      If IsGadget(curGadget)
         Select GadgetType(curGadget)
            Case #PB_GadgetType_CheckBox, #PB_GadgetType_ComboBox, #PB_GadgetType_ListIcon, #PB_GadgetType_Spin, #PB_GadgetType_Button
               PostEvent(#PB_Event_Gadget, EventWindow(), curGadget, #PB_EventType_Focus)
         EndSelect
      EndIf
   EndIf
   prevGadget = curGadget
EndProcedure

CompilerIf 1   ; after changing this value to 0, you will see no effect
   BindEvent(#PB_Event_Repaint, @GenerateFocusEvents())
CompilerEndIf


CompilerIf #PB_Compiler_IsMainFile
   ; -- Demo
   Define.i event
   
   If OpenWindow(0, 100, 100, 300, 250, "Focus event demo") = 0
      MessageRequester("Fatal error", "Can't open main window.")
      End
   EndIf   
   
   CheckBoxGadget(0, 20, 20, 120, 25, "Checkbox")
   
   ComboBoxGadget(1, 20, 55, 120, 25)
   AddGadgetItem (1, -1, "ComboBox item")
   SetGadgetState(1, 0)
   
   ListIconGadget(2, 20,  90, 120, 60, "Foo", 40)
   AddGadgetItem (2, -1, "42")
   
   SpinGadget    (3, 20, 165, 120, 25, 0, 5)
   ButtonGadget  (4, 20, 200, 120, 25, "OK")
   
   Repeat
      event = WaitWindowEvent()
      
      Select event
         Case #PB_Event_Gadget
            Select EventType()
               Case #PB_EventType_LostFocus
                  Debug Str(EventGadget()) + ": LostFocus"
               Case #PB_EventType_Focus
                  Debug Str(EventGadget()) + ": GotFocus"
               Default   
                  Debug Str(EventGadget()) + ": other event"
            EndSelect      
      EndSelect
   Until event = #PB_Event_CloseWindow
CompilerEndIf

-------------------------------------------------

My best tricks & tips from 15+ years
Create arrays elegantly
Extended date library
Save JSON data with object members well-arranged
Evaluate and process math expressions
Functions for sets
Statistics with R
Thue-Morse sequence
Natural sorting
Sort array indexes and parallel arrays
Time profiling
VectorIcons
Generate focus events
Last edited by Little John on Thu Jul 03, 2025 7:16 am, edited 1 time in total.
Quin
Addict
Addict
Posts: 1122
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: Generate missing event types #PB_EventType_LostFocus and #PB_EventType_Focus

Post by Quin »

Very cool and useful, thanks for sharing!
mestnyi
Addict
Addict
Posts: 1098
Joined: Mon Nov 25, 2013 6:41 am

Re: Generate missing event types #PB_EventType_LostFocus and #PB_EventType_Focus

Post by mestnyi »

It's a very good idea. :idea:
Quin
Addict
Addict
Posts: 1122
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: Generate missing event types #PB_EventType_LostFocus and #PB_EventType_Focus

Post by Quin »

There is a problem with this trick:
If you select on EventGadget() in your callback or main loop and get a button event, EventType() won't be able to tell you if you got a focus event or a press event, so even focusing the button will cause the logic that should only get triggered on button press :mrgreen:
All the more reason I would love to see this natively in PB, the gadget library is seriously lacking without it IMO.
Little John
Addict
Addict
Posts: 4775
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: Generate missing event types #PB_EventType_LostFocus and #PB_EventType_Focus

Post by Little John »

Hi,

can you please post working code that demonstrates the problem?

Using the code in the first post of this thread (with PB 6.20 (x64) on Windows 11), I can't confirm the issue.
When pressing the TAB key, I get the messages “4: GotFocus” and “4: LostFocus”, when the focus enters/leaves the button.
When I click at the button with the mouse or press the SPACE key while the button has the focus, I get the message “4: other event”.
Quin
Addict
Addict
Posts: 1122
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: Generate missing event types #PB_EventType_LostFocus and #PB_EventType_Focus

Post by Quin »

Hi,
Actually, the problem is not with your code, it's with how my logic workes, and the fact that EventType() can't return a #PB_EventType_ButtonPress event or something similar.
In my app, I don't really care about the focus events of a button, but I care when it's pressed. Before I added this logic, my function was like:

Code: Select all

Procedure MainGadgetEvents()
  Select EventGadget()
    Case #Gadget_MyButton
      ; ...
  EndSelect
EndProcedure
however, this hack breaks code like this. You have to check if the event type isn't a focus event, and just do your press logic in the default case. Ugly, but it works, until Fred hopefully improves the gadget lib...
Little John
Addict
Addict
Posts: 4775
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: Generate missing event types #PB_EventType_LostFocus and #PB_EventType_Focus

Post by Little John »

Quin wrote: however, this hack breaks code like this. You have to check if the event type isn't a focus event, and just do your press logic in the default case.
I understand now. Thanks for the explanation. Yes, when using this hack, existing code must be adapted accordingly.
Quin wrote: Ugly, but it works, until Fred hopefully improves the gadget lib...
I'm glad that the hack works for you. I was very happy myself when I found this workaround. :-)

Me too would appreciate it, if PureBasic would natively support both focus events for all its gadgets. However, old code then has to be adapted as well, no? :-)
Quin
Addict
Addict
Posts: 1122
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: Generate missing event types #PB_EventType_LostFocus and #PB_EventType_Focus

Post by Quin »

Little John wrote: Wed Apr 16, 2025 7:43 pm I'm glad that the hack works for you. I was very happy myself when I found this workaround. :-)
Yup, it works well, although in my main app (over 10K LOC) I'm having issues with it for combo boxes. I haven't been able to track it down yet though and it works for everything else, so I'm not sure on that one. If I track it down though I'll report back here.
Little John wrote: Wed Apr 16, 2025 7:43 pm
Me too would appreciate it, if PureBasic would natively support both focus events for all its gadgets. However, old code then has to be adapted as well, no? :-)
Only if that old code is using hacks, and even then the default case for EventType() other than #PB_EventType_Focus and #PB_EventType_LostFocus would be the #PB_EventType_ButtonPress, so it would still work.
User avatar
mk-soft
Always Here
Always Here
Posts: 6202
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Generate missing event types #PB_EventType_LostFocus and #PB_EventType_Focus

Post by mk-soft »

Quin wrote: Wed Apr 16, 2025 7:06 pm Hi,
Actually, the problem is not with your code, it's with how my logic workes, and the fact that EventType() can't return a #PB_EventType_ButtonPress event or something similar.
In my app, I don't really care about the focus events of a button, but I care when it's pressed. Before I added this logic, my function was like:

Code: Select all

Procedure MainGadgetEvents()
  Select EventGadget()
    Case #Gadget_MyButton
      ; ...
  EndSelect
EndProcedure
however, this hack breaks code like this. You have to check if the event type isn't a focus event, and just do your press logic in the default case. Ugly, but it works, until Fred hopefully improves the gadget lib...
I have also already added EventType that also affect buttons.
So you have to use the event type #PB_EventType_LeftClick.

Code: Select all

Procedure MainGadgetEvents()
  Select EventGadget()
    Case #Gadget_MyButton
      Select EventType()
        Case #PB_EventType_LeftClick
          
        Case #PB_EventType_Focus
          
        Case #PB_EventType_LostFocus
          
      EndSelect
      
  EndSelect
EndProcedure
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
Quin
Addict
Addict
Posts: 1122
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: Generate missing event types #PB_EventType_LostFocus and #PB_EventType_Focus

Post by Quin »

Oh, that's cool, thanks MK-Soft! I didn't know #PB_EventType_LeftClick is triggered on button press. I'll have to test if this also works with the keyboard, e.g. pressing space on a button.
Quin
Addict
Addict
Posts: 1122
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: Generate missing event types #PB_EventType_LostFocus and #PB_EventType_Focus

Post by Quin »

Quin wrote: Wed Apr 16, 2025 8:49 pm ...in my main app (over 10K LOC) I'm having issues with it for combo boxes. I haven't been able to track it down yet though and it works for everything else, so I'm not sure on that one. If I track it down though I'll report back here.
Figured it out, once again, as with Idle's networking code, it was a bug on my side. Thanks for your great work!
Post Reply