SpinGadget Focus/Lostfocus eventtypes

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
Geert
User
User
Posts: 47
Joined: Thu Aug 16, 2012 3:17 pm
Location: Belgium
Contact:

SpinGadget Focus/Lostfocus eventtypes

Post by Geert »

It would be nice to have a SpinGadget that supports the focus and lostfocus events, just like the other "input" gadgets (stringgadget and editable comboboxgadget).
On Windows I have already made a workaround (see below), but I don't know how it could be done on MacOSX (cocoa) or Linux.

Code: Select all

Procedure.i Focus_Callback(hWnd.i,uMsg,wParam,lParam) ;hWnd=0,uMsg=Gadget,wParam=Window,lParam=1,lParam=0=>remove focusevent
 CompilerIf #PB_Compiler_OS=#PB_OS_Windows  
  Static Dim OldProc.i(0)
  Static size.l=0
  Protected tl.l,id.i
  
  If hWnd=0  
   Select GadgetType(uMsg)
    Case #PB_GadgetType_ComboBox
     id=FindWindowEx_(GadgetID(uMsg),0,"Edit",0)
    Default
     id=GadgetID(uMsg)
   EndSelect
   If lParam=0
    For tl=1 To size
     If id=OldProc(tl*4-1)
      SetWindowLong_(id,#GWL_WNDPROC,OldProc(tl*4))
      OldProc(tl*4-1)=0
      Break
     EndIf
    Next
   Else
    For tl=1 To size
     If OldProc(tl*4-1)=0
      Break
     EndIf
    Next
    If tl>size
     size=tl
     ReDim OldProc.i(tl*4)    
    EndIf
    OldProc(tl*4-1)=id
    OldProc(tl*4-2)=uMsg
    OldProc(tl*4-3)=wParam
    OldProc(tl*4)=SetWindowLong_(id,#GWL_WNDPROC,@Focus_Callback())
   EndIf
  Else
   For tl=1 To size
    If hWnd=OldProc(tl*4-1)     
     Select uMsg
      Case #WM_SETFOCUS
       PostEvent(#PB_Event_Gadget,OldProc(tl*4-3),OldProc(tl*4-2),#PB_EventType_Focus)
      Case #WM_KILLFOCUS
       PostEvent(#PB_Event_Gadget,OldProc(tl*4-3),OldProc(tl*4-2),#PB_EventType_LostFocus)
      Case #WM_DESTROY
       SetWindowLong_(hWnd,#GWL_WNDPROC,OldProc(tl*4))
       OldProc(tl*4-1)=0
     EndSelect
     ProcedureReturn CallWindowProc_(OldProc(tl*4),hwnd,uMsg,wParam,lParam)
    EndIf
   Next
  EndIf 
 CompilerEndIf ;MacOSX, Linux -> TODO 
 ProcedureReturn 1
EndProcedure

If OpenWindow(0, 0, 0, 140, 150, "SpinGadget Focus", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
 SpinGadget(1, 20, 20, 100, 25, 0, 1000)
 SpinGadget(2, 20, 50, 100, 25, 0, 1000)
 ComboBoxGadget(3, 20, 80, 100, 25,#PB_ComboBox_Editable) ;already supports focus/lostfocus
 Focus_Callback(0,1,0,1)
 Focus_Callback(0,2,0,1)
 SetActiveGadget(1)
 
 Repeat
  Event = WaitWindowEvent()
  If Event = #PB_Event_Gadget   
   Select EventType()
    Case #PB_EventType_Focus
     Debug Str(EventGadget())+" -> focus"
    Case #PB_EventType_Change
     Debug Str(EventGadget())+" -> change"
    Case #PB_EventType_LostFocus
     Debug Str(EventGadget())+" -> lostfocus"
   EndSelect  
  EndIf
 Until Event = #PB_Event_CloseWindow
EndIf 
End
Visit my website: https://www.basic-apps.com

Home of SoftMaths, ToolsForIcons, Checksums, MoonPhases, ...
BorisTheOld
Enthusiast
Enthusiast
Posts: 542
Joined: Tue Apr 24, 2012 5:08 pm
Location: Ontario, Canada

Re: SpinGadget Focus/Lostfocus eventtypes

Post by BorisTheOld »

Geert wrote:It would be nice to have a SpinGadget that supports the focus and lostfocus events......
It would be nice to have GotFocus and LostFocus events for all GUI gadgets -- and there are already a number of requests for specific gadgets, like buttons.

It's almost impossible to write complex cross-platform GUI applications without those two events, and I'm surprised they don't already exist in PB, especially as the underlying OS APIs support them. It's not as if "focus" events are an obscure GUI feature.

We're currently looking into two cross-platform techniques to avoid using OS API features. The first is to track the focus status of every gadget. This requires monitoring the mouse, keystrokes, and SetActiveGadget commands, and generating our own custom GotFocus and LostFocus events. The second, and preferred method for us, is to write custom gadgets based on the Canvas gadget.

Unfortunately, all this extra work takes valuable time away from converting our existing Power Basic code to PB, and from writing new cross-platform applications.
For ten years Caesar ruled with an iron hand, then with a wooden foot, and finally with a piece of string.
~ Spike Milligan
User avatar
deeproot
Enthusiast
Enthusiast
Posts: 284
Joined: Thu Dec 17, 2009 12:00 pm
Location: Llangadog, Wales, UK
Contact:

Re: SpinGadget Focus/Lostfocus eventtypes

Post by deeproot »

I'm bumping this thread, prompted by a failure in a large program when testing PB 5.21 LTS Beta.

I suspect there is a change of behaviour with SpinGadget events in 5.21 LTS, probably due to fixing other issues. Unfortunately it breaks something that was previously working, though I guess it's not a bug!

This thread is related - http://www.purebasic.fr/english/viewtop ... =7&t=57000

In above thread, PB descibes a method to detect Focus for a SpinGadget. I do something very similar - simply keep track of gadgets to determine the first time any event is fired. This avoids directly referencing any undocumented events or platform specific stuff. Up to PB 5.20 this method was perfectly acceptable.

Previous to 5.21 an 'editable' SpinGadget fired some kind of event as soon as the user clicked in the edit area or an up/down button. Unless a value is changed there is now no event, so this method can no longer be used to reliably detect when it gets the focus. This is a problem if special actions need to be performed when the user moves to the gadget.

As a result I think we need some easy and cross-platform way to find when a SpinGadget gets the Focus. Alternatively a different event such as Mouse_down could solve the problem just as well.

OK, I know it is possible to construct some other solution around the issue, but straightforward Focus/LostFocus events would be preferable.
Post Reply