#PB_EventType_LostFocus Problem

Just starting out? Need help? Post your questions and find answers here.
Buddy
New User
New User
Posts: 2
Joined: Wed Feb 13, 2013 9:09 am

#PB_EventType_LostFocus Problem

Post by Buddy »

I've got a window with two StringGadget's. Upon losing focus, I reformat the text that's been entered into each StringGadget. The problem I can't seem to solve is getting a #PB_EventType_LostFocus event to occur when clicking on the File -> Save menu. I don't want the user to have to first hit the Tab key or click on another Gadget to change focus. The following code illustrates the situation. After entering "1 2 3" into the upper StringGadget and changing focus to the lower StringGadget, the upper text is reformatted to "123" as expected. After entering "4 5 6" into the lower StringGadget and clicking on File -> Save, the lower text is not reformatted and FileSave() receives "4 5 6" instead of "456". Why does clicking on File -> Save not first cause a #PB_EventType_LostFocus event to the Gadget currently in focus? Is there a simple solution to this problem?

Code: Select all

EnableExplicit

Enumeration
  #FileSave
  #FileExit
EndEnumeration

Procedure FileSave(TextA.s,TextB.s)
  
  Debug "File -> Save: " + "(" + TextA + ")   (" +  TextB + ")"
    
EndProcedure

;
; -----------------------
;
;        Main()
;
; -----------------------
;

Define MainWindow.l
Define SystemMenu.l
Define Gadget1.l
Define Gadget2.l
Define Text1.s
Define Text2.s
Define Event.l
Define EventGadget.l
Define EventType.l
Define Quit.l

MainWindow = OpenWindow(#PB_Any,0,0,200,150,"Test",#PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
SystemMenu = CreateMenu(#PB_Any,WindowID(MainWindow))
MenuTitle("File")
MenuItem(#FileSave,"Save")
MenuBar()
MenuItem(#FileExit,"Exit")
Gadget1 = StringGadget(#PB_Any,15,25,170,20,Text1)
Gadget2 = StringGadget(#PB_Any,15,70,170,20,Text2)
Quit = #False

Repeat
  
  Event = WaitWindowEvent()
  EventGadget = EventGadget()
  EventType = EventType()
  
  Select Event
      
    Case #PB_Event_Menu
      
      Select EventMenu()
          
        Case #FileSave
          FileSave(Text1,Text2)
          
        Case #FileExit
          Quit = #True
          
      EndSelect
      
    Case #PB_Event_Gadget
      
      Select EventGadget
          
        Case Gadget1
          If EventType = #PB_EventType_Change
            Text1 = GetGadgetText(Gadget1)
          ElseIf EventType = #PB_EventType_LostFocus
            Text1 = ReplaceString(Text1," ","")
            SetGadgetText(Gadget1,Text1)
          EndIf
          
        Case Gadget2
          If EventType = #PB_EventType_Change
            Text2 = GetGadgetText(Gadget2)
          ElseIf EventType = #PB_EventType_LostFocus
            Text2 = ReplaceString(Text2," ","")
            SetGadgetText(Gadget2,Text2)
          EndIf
          
      EndSelect
      
    Case #PB_Event_CloseWindow
      Quit = #True
      
  EndSelect
  
Until Quit = #True

End
User avatar
BasicallyPure
Enthusiast
Enthusiast
Posts: 536
Joined: Thu Mar 24, 2011 12:40 am
Location: Iowa, USA

Re: #PB_EventType_LostFocus Problem

Post by BasicallyPure »

Hi,
Your code works correctly when run using Linux but not with windows.
I think there should be lost focus events when 'file' is clicked but that doesn't seem to be the case with windows.

I would suggest possibly using GetActiveGadget() with some code just before filesave to trigger the processing of the text in the active gadget.

B.P.
BasicallyPure
Until you know everything you know nothing, all you have is what you believe.
Buddy
New User
New User
Posts: 2
Joined: Wed Feb 13, 2013 9:09 am

Re: #PB_EventType_LostFocus Problem

Post by Buddy »

BasicallyPure wrote:Your code works correctly when run using Linux but not with windows.
I think there should be lost focus events when 'file' is clicked but that doesn't seem to be the case with windows.
Thank you for confirming there's a bug in the Windows library. I was pretty sure that was the case, but wanted independent verification.
BasicallyPure wrote:I would suggest possibly using GetActiveGadget() with some code just before filesave to trigger the processing of the text in the active gadget.
Simply triggering a focus change when a menu event occurs isn't quite enough. It's necessary to defer the processing of the menu event while the lost focus event is processed:

Code: Select all

SavedEvent = 0

Repeat
  
  If SavedEvent = 0
    Event = WaitWindowEvent()
    EventMenu = EventMenu()
    If Event = #PB_Event_Menu
      SavedEvent = Event
      SavedEventMenu = EventMenu
      SetActiveGadget(-1)
    Else
      EventGadget = EventGadget()
      EventType = EventType()
      EventWindow = EventWindow()
    EndIf
  EndIf
  If SavedEvent <> 0
    Event = WindowEvent()
    If Event <> 0
      EventMenu = EventMenu()
      EventGadget = EventGadget()
      EventType = EventType()
      EventWindow = EventWindow()
    Else
      Event = SavedEvent
      EventMenu = SavedEventMenu
      SavedEvent = 0
    EndIf
  EndIf
  
  Select Event
User avatar
skywalk
Addict
Addict
Posts: 3997
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: #PB_EventType_LostFocus Problem

Post by skywalk »

Another option is to use PostEvent() with a gui tracking variable...

Code: Select all

EnableExplicit
Global.i gui
Enumeration
  #FileSave
  #FileExit
EndEnumeration
Procedure FileSave(TextA.s,TextB.s)
  Debug "File -> Save: " + "(" + TextA + ")   (" +  TextB + ")"
EndProcedure
Define MainWindow.l
Define SystemMenu.l
Define Gadget1.l
Define Gadget2.l
Define Text1.s
Define Text2.s
Define Event.l
Define EventGadget.l
Define EventType.l
Define Quit.l
MainWindow = OpenWindow(#PB_Any,0,0,200,150,"Test",#PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
SystemMenu = CreateMenu(#PB_Any,WindowID(MainWindow))
MenuTitle("File")
MenuItem(#FileSave,"Save")
MenuBar()
MenuItem(#FileExit,"Exit")
Gadget1 = StringGadget(#PB_Any,15,25,170,20,Text1)
Gadget2 = StringGadget(#PB_Any,15,70,170,20,Text2)
Quit = #False
Repeat
  Event = WaitWindowEvent()
  EventGadget = EventGadget()
  EventType = EventType()
  Select Event
  Case #PB_Event_Menu
    Select EventMenu()
    Case #FileSave
      If gui
        PostEvent(#PB_Event_Gadget, MainWindow, Gadget1, #PB_EventType_LostFocus)
        Debug "Changes being processed...Try again."
      Else
        FileSave(Text1,Text2)
      EndIf
    Case #FileExit
      If gui
        PostEvent(#PB_Event_Gadget, MainWindow, Gadget1, #PB_EventType_LostFocus)
        Debug "Changes being processed...Try again."
      Else
        Quit = #True
      EndIf
    EndSelect
  Case #PB_Event_Gadget
    Select EventGadget
    Case Gadget1
      If EventType = #PB_EventType_Change
        Text1 = GetGadgetText(Gadget1)
        gui = 1
      ElseIf EventType = #PB_EventType_LostFocus
        Text1 = ReplaceString(Text1," ","")
        SetGadgetText(Gadget1,Text1)
        gui = 0
      EndIf
    Case Gadget2
      If EventType = #PB_EventType_Change
        Text2 = GetGadgetText(Gadget2)
      ElseIf EventType = #PB_EventType_LostFocus
        Text2 = ReplaceString(Text2," ","")
        SetGadgetText(Gadget2,Text2)
      EndIf
    EndSelect
  Case #PB_Event_CloseWindow
    Quit = #True
  EndSelect
Until Quit = #True
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8433
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: #PB_EventType_LostFocus Problem

Post by netmaestro »

The reason your code doesn't work as expected in Windows is that merely opening the menu does not cause the string gadget to lose focus. Menus don't grab keyboard focus in and of themselves. However, often, even usually, the actions taken when a menu item is chosen will shift the focus, triggering your handler.
BERESHEIT
User avatar
skywalk
Addict
Addict
Posts: 3997
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: #PB_EventType_LostFocus Problem

Post by skywalk »

I was hoping so, but I had a break point in my gadget's lost focus event and it never fires prior to executing the menu event.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Little John
Addict
Addict
Posts: 4527
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: #PB_EventType_LostFocus Problem

Post by Little John »

skywalk wrote:

Code: Select all

    Select EventMenu()
    Case #FileSave
      If gui
        PostEvent(#PB_Event_Gadget, MainWindow, Gadget1, #PB_EventType_LostFocus)
        Debug "Changes being processed...Try again."
I wouldn't code it this way, because the user would have to click twice on the File/Save menu item in order to save her/his text. So s/he probably would send a bug report to the programmer.

I'd rather put the code for cleaning up the contents of the string gadgets in a macro or procedure, and then call this macro/procedure not only on #PB_EventType_LostFocus, but also on the File/Save menu event. Simple and straightforward.
Here is the original code, changed accordingly (tested with PB 5.44 LTS on Windows 10 and Linux Mint 18.2 Cinnamon):

Code: Select all

EnableExplicit

; Menu items
Enumeration
   #FileSave
   #FileExit
EndEnumeration

Procedure FileSave (TextA.s, TextB.s)
   Debug "File -> Save: " + "(" + TextA + ")   (" +  TextB + ")"
EndProcedure

Macro CleanupStringGadgetContent (_gadget_, _text_)
   _text_ = RemoveString(_text_, " ")
   SetGadgetText(_gadget_, _text_)
EndMacro

; -----------------------
;
;        Main()
;
; -----------------------

Define.i MainWindow, Gadget1, Gadget2, LastFocusGadget
Define.s Text1, Text2
Define.i Event, EventGadget, EventType, Quit

MainWindow = OpenWindow(#PB_Any, 0,0,200,150, "Test", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
If CreateMenu(#PB_Any, WindowID(MainWindow))
   MenuTitle("File")
   MenuItem(#FileSave, "Save")
   MenuBar()
   MenuItem(#FileExit, "Exit")
EndIf
Gadget1 = StringGadget(#PB_Any, 15,25,170,20, Text1)
Gadget2 = StringGadget(#PB_Any, 15,70,170,20, Text2)
LastFocusGadget = 0
Quit = #False

Repeat
   Event = WaitWindowEvent()
   EventGadget = EventGadget()
   EventType = EventType()
   
   Select Event
      Case #PB_Event_Menu
         Select EventMenu()

            Case #FileSave
               Select LastFocusGadget
                  Case Gadget1
                     CleanupStringGadgetContent(Gadget1, Text1)
                  Case Gadget2
                     CleanupStringGadgetContent(Gadget2, Text2)
               EndSelect   
               FileSave(Text1, Text2)
               
            Case #FileExit
               Quit = #True
         EndSelect
         
      Case #PB_Event_Gadget
         Select EventGadget

            Case Gadget1
               If EventType = #PB_EventType_Change
                  Text1 = GetGadgetText(Gadget1)
               ElseIf EventType = #PB_EventType_LostFocus
                  CleanupStringGadgetContent(Gadget1, Text1)
               EndIf
               LastFocusGadget = Gadget1
               
            Case Gadget2
               If EventType = #PB_EventType_Change
                  Text2 = GetGadgetText(Gadget2)
               ElseIf EventType = #PB_EventType_LostFocus
                  CleanupStringGadgetContent(Gadget2, Text2)
               EndIf
               LastFocusGadget = Gadget2
         EndSelect
         
      Case #PB_Event_CloseWindow
         Quit = #True
   EndSelect
Until Quit = #True
P.S.: For events etc. do not use variables of type .l (long), but always of type .i (integer).
User avatar
skywalk
Addict
Addict
Posts: 3997
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: #PB_EventType_LostFocus Problem

Post by skywalk »

You are correct, but I was only using the original posted code with small addition of postevent. I agree it is inefficient for 2 menu clicks, but I was emphasizing the lost, lost focus. :)
I recently replaced a callback in 1of my GUI's for the inline PB event loop and started losing lost focus events.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Post Reply