Page 1 of 1

TAB Order and BindGadgetEvent() problem

Posted: Mon Aug 21, 2017 10:15 am
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

Re: TAB Order and BindGadgetEvent() problem

Posted: Mon Aug 21, 2017 11:46 am
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

Re: TAB Order and BindGadgetEvent() problem

Posted: Mon Aug 21, 2017 11:56 am
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

Re: TAB Order and BindGadgetEvent() problem

Posted: Mon Aug 21, 2017 12:03 pm
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

Re: TAB Order and BindGadgetEvent() problem

Posted: Mon Aug 21, 2017 12:19 pm
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

Re: TAB Order and BindGadgetEvent() problem

Posted: Mon Aug 21, 2017 2:57 pm
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?