TAB Order and BindGadgetEvent() problem

Windows specific forum
RichardL
Enthusiast
Enthusiast
Posts: 532
Joined: Sat Sep 11, 2004 11:54 am
Location: UK

TAB Order and BindGadgetEvent() problem

Post by RichardL »

Good morning,
I'm not sure if this is a feature, or a bug (heaven forbid!), or I'm doing something stupid.

I have several StringGadget() in a row, created in a loop and the TAB key order lets me move back and fore between them.

If I write the program using the conventional PB EventMangement style all works well and I can skip some StringGadgets (In the real application the program completes them for me, but the user can edit them if wanted.) The cursor ends up where I want it.

If I write the program using BindGadgetEvent() to acheive the same effect I can still skip some StringGadgets but the cursor does not appear in the StringGadget I have jumped to even though keyboard input does go to the gadget.

Here are my simplified examples... I would much rather make the BindGadgetEvent() method work as a whole lot of other things become easier for me.

Any comments welcomed.
RichardL

Code: Select all

; PB5.44LTS + Windows10

; Version 1 using normal event management
; =======================================

; Make display
OpenWindow(0, 0, 0, 500, 140, "Set StringGadget Test.     Use TAB key to progress...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
X = 5
For n = 1 To 8
  StringGadget  (n, X, 10, 50, 20, Str(n))
 X+55
Next

SetActiveGadget(4) ; Start at #4.... See CURSOR OK

; Event manager
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
      
    Case #PB_Event_Gadget
      
      Select EventGadget()
        Case 6
          If EventType() = #PB_EventType_LostFocus
            SetActiveGadget(2) ; Jumps to #2... See CURSOR OK
          EndIf
          
      EndSelect
      
  EndSelect
ForEver

Code: Select all

; Version 2 using BindGadgetEvent()
; =================================
Declare Stringin()

OpenWindow(0, 0, 0, 500, 140, "Set StringGadget Test.     Use TAB key to progress...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
X = 5
For n = 1 To 8
  StringGadget  (n, X, 10, 50, 20, Str(n))
  BindGadgetEvent(n,@Stringin()) ; Disable this line and un-comment the event mangager stuff.
  X+55
Next

SetActiveGadget(4) ; Start at #4.... See CURSOR OK

; Event manager
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
      
    Case #PB_Event_Gadget
     
      
  EndSelect
ForEver

Procedure Stringin() ; Here when Get/Lost focus or content Changes
  
  ; When  we get to #6 jump back to #2 (#1,#7 and #8 filled in automatically)
  If EventGadget() = 6
    If EventType() = #PB_EventType_LostFocus
      SetActiveGadget(2)                        ; Jumps to #2... but NO CURSOR!
    EndIf
  EndIf
  
EndProcedure
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4636
Joined: Sun Apr 12, 2009 6:27 am

Re: TAB Order and BindGadgetEvent() problem

Post by RASHAD »

Hi RichardL
Adapt the next snippet for your needs
Use |#WS_TABSTOP to enable Tab key
Use &~ #WS_TABSTOP to disable Tab key

Code: Select all

; Version 2 using BindGadgetEvent()
; =================================
Declare Stringin()

OpenWindow(0, 0, 0, 500, 140, "Set StringGadget Test.     Use TAB key to progress...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
X = 5
For n = 1 To 8
  StringGadget  (n, X, 10, 50, 20, Str(n))
  BindGadgetEvent(n,@Stringin()) ; Disable this line and un-comment the event mangager stuff.
  X+55
Next

SetWindowLongPtr_(GadgetID(1),#GWL_STYLE, GetWindowLongPtr_(GadgetID(1),#GWL_STYLE) &~ #WS_TABSTOP)
SetWindowLongPtr_(GadgetID(7),#GWL_STYLE, GetWindowLongPtr_(GadgetID(7),#GWL_STYLE) &~ #WS_TABSTOP)
SetWindowLongPtr_(GadgetID(8),#GWL_STYLE, GetWindowLongPtr_(GadgetID(8),#GWL_STYLE) &~ #WS_TABSTOP)

SetActiveGadget(4) ; Start at #4.... See CURSOR OK

; Event manager
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
     
    Case #PB_Event_Gadget
     
     
  EndSelect
ForEver

Procedure Stringin() ; Here when Get/Lost focus or content Changes 
  ; When  we get to #6 jump back to #2 (#1,#7 and #8 filled in automatically)
  If EventGadget() = 6
    If EventType() = #PB_EventType_LostFocus
      SetActiveGadget(2)                        ; Jumps to #2... but NO CURSOR!
    EndIf
  EndIf
 
EndProcedure
Egypt my love
User avatar
Bisonte
Addict
Addict
Posts: 1226
Joined: Tue Oct 09, 2007 2:15 am

Re: TAB Order and BindGadgetEvent() problem

Post by Bisonte »

I realized that some SendMessage_() don't work in a BindGadgetEvent procedure...
But PostMessage_() instead... works well. I think SetActiveGadget uses internally SendMessage_() so
this is a little "workaround" ;)

Code: Select all

Procedure Stringin() ; Here when Get/Lost focus or content Changes
 
  ; When  we get to #6 jump back to #2 (#1,#7 and #8 filled in automatically)
  If EventGadget() = 6
    If EventType() = #PB_EventType_LostFocus
      ;SetActiveGadget(2)                        ; Jumps to #2... but NO CURSOR!
      PostMessage_(GadgetID(2), #WM_ACTIVATE, #WA_ACTIVE, 0)
    EndIf
  EndIf
 
EndProcedure
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
English is not my native language... (I often use DeepL to translate my texts.)
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: TAB Order and BindGadgetEvent() problem

Post by IdeasVacuum »

Hi Richard

I think you may have discovered a PB bug, or at least an undocumented limitation of BindGadgetEvent()

Without BindGadgetEvent() you can still have a tidy main loop like this:

Code: Select all

; Version 3 not using BindGadgetEvent()
; =====================================
Declare Stringin()

OpenWindow(0, 0, 0, 500, 140, "Set StringGadget Test. Use TAB key to progress...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
X = 5
For n = 1 To 8
  StringGadget  (n, X, 10, 50, 20, Str(n))
  ;BindGadgetEvent(n,@Stringin()) ; Disable this line and un-comment the event mangager stuff.
  X+55
Next

SetActiveGadget(4) ; Start at #4.... See CURSOR OK

; Event manager
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
     
    Case #PB_Event_Gadget: Stringin()
     
     
  EndSelect
ForEver

Procedure Stringin() ; Here when Get/Lost focus or content Changes
 
  ; When  we get to #6 jump back to #2 (#1,#7 and #8 filled in automatically) ;This means #6 is never filled
  If EventGadget() = 6
    ;If EventType() = #PB_EventType_LostFocus
      SetActiveGadget(2)                        ; Jumps to #2... but NO CURSOR!
    ;EndIf
  EndIf
 
EndProcedure
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4636
Joined: Sun Apr 12, 2009 6:27 am

Re: TAB Order and BindGadgetEvent() problem

Post by RASHAD »

a window already has the #PB_Shortcut_Tab and #PB_Shortcut_Tab|#PB_Shortcut_Shift shortcuts to handle tab and shift-tab correctly trough the gadgets.
No PB bug
Windows has its own routine to handle using Tab key to rotate between objects
That is why PostMessage_() can work successfully and not SendMessage_()
The PostMessage function places (posts) a message in the message queue associated with the thread that created the specified window and then returns without waiting for the thread to process the message
Egypt my love
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: TAB Order and BindGadgetEvent() problem

Post by IdeasVacuum »

Hi Rashad

... that is true, but should it be the case that BindGadgetEvent() has a detrimental effect on code that works fine without the binding?
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Post Reply