Is it possible to select text natively upon setting focus?

Just starting out? Need help? Post your questions and find answers here.
User avatar
Shardik
Addict
Addict
Posts: 2058
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: Is it possible to select text natively upon setting focu

Post by Shardik »

I have programmed a cross-platform example utilizing OS-specific API
functions which autoselects the text in a StringGadget on moving the
mouse cursor over the StringGadget and which deselects the text on
the cursor leaving the Gadget. I have tested it to work on these OSes:

- Windows XP SP3 (32 Bit)
- Windows 7 (32 Bit)
- Windows 7 (64 Bit with PB x64)
- MacOS X 10.6.8
- andLinux/Kubuntu 9.04 (32 Bit)
- Kubuntu 10.04 (32 Bit)
- Ubuntu/Unity 11.04 (32 Bit)

Code: Select all

CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_MacOS
    ImportC ""
      GetEventClass(Event.L)
      HIViewNewTrackingArea(HIViewRef.L, Shape.L, TrackingAreaID.Q, *TrackingAreaRef)
      SetControlData(ControlRef.L, ControlPartCode.L, TagName.L, BufferSize.L, *Buffer)
    EndImport

    #kControlEditTextPart = 5
    #kControlEditTextSelectionTag = 'sele'
    #kEventClassControl = 'cntl'
    #kEventControlTrackingAreaEntered = 23
    #kEventControlTrackingAreaExited = 24

    Structure ControlEditTextSelectionRec
      SelStart.W
      SelEnd.W
    EndStructure

    Structure EventTypeSpec
      EventClass.L
      EventKind.L
    EndStructure

    Dim EventTypes.EventTypeSpec(1)

    ProcedureC EventHandler(*NextEventHandler, Event.L, UserData.L)
      Protected TextSelection.ControlEditTextSelectionRec

      Select GetEventKind_(Event)
        Case #kEventControlTrackingAreaEntered
          TextSelection\SelStart = 0
          TextSelection\SelEnd = Len(GetGadgetText(0))
          SetActiveGadget(0)
        Case #kEventControlTrackingAreaExited
          TextSelection\SelStart = 0
          TextSelection\SelEnd = 0
      EndSelect

      SetControlData(GadgetID(0), #kControlEditTextPart, #kControlEditTextSelectionTag, SizeOf(ControlEditTextSelectionRec), @TextSelection)

      If *NextEventHandler
        CallNextEventHandler_(*NextEventHandler, Event)
      EndIf
    EndProcedure
  CompilerCase #PB_OS_Linux
    Enumeration
      #EnterGadgetEvent
      #LeaveGadgetEvent
    EndEnumeration

    ProcedureC EventHandler(*Widget.GtkWidget, *Event.GdkEventMotion, UserData)
      Select UserData
        Case #EnterGadgetEvent
          gtk_editable_select_region_(GadgetID(0), 0, Len(GetGadgetText(0)))    
        Case #LeaveGadgetEvent
          gtk_editable_select_region_(GadgetID(0), 0, 0)    
      EndSelect
    EndProcedure
  CompilerCase #PB_OS_Windows
    Procedure IsMouseOverGadget(GadgetID)
      GetWindowRect_(GadgetID(GadgetID), GadgetRect.RECT)
      ProcedureReturn PtInRect_(@GadgetRect, DesktopMouseY() << 32 | DesktopMouseX())
    EndProcedure
CompilerEndSelect

OpenWindow(0, 0, 0, 200, 100, "Autoselect text", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
StringGadget(0, 50, 40, 100, 20, "Test")

CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_MacOS
    EventTypes(0)\EventClass = #kEventClassControl
    Eventtypes(0)\EventKind = #kEventControlTrackingAreaEntered
    EventTypes(1)\EventClass = #kEventClassControl
    Eventtypes(1)\EventKind = #kEventControlTrackingAreaExited
    HIViewNewTrackingArea(GadgetID(0), 0, 0, 0)
    EventHandlerUPP = NewEventHandlerUPP_(@EventHandler())
    InstallEventHandler_(GetControlEventTarget_(GadgetID(0)), EventHandlerUPP, 2, @EventTypes(), @EventHandler(), 0)
  CompilerCase #PB_OS_Linux
    gtk_widget_add_events_(GadgetID(0), #GDK_ENTER_NOTIFY_MASK | #GDK_LEAVE_NOTIFY_MASK)
    g_signal_connect_data_(GadgetID(0), "enter-notify-event", @EventHandler(), #EnterGadgetEvent, 0, 0)
    g_signal_connect_data_(GadgetID(0), "leave-notify-event", @EventHandler(), #LeaveGadgetEvent, 0, 0)
CompilerEndSelect

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    CompilerIf #PB_Compiler_OS = #PB_OS_Windows
      Case #WM_MOUSEMOVE
        If IsMouseOverGadget(0)
          If IsTextSelected = #False
            SetActiveGadget(0)
            SendMessage_(GadgetID(0), #EM_SETSEL, 0, -1)
            IsTextSelected = #True
          EndIf
        EndIf
      Case #WM_MOUSELEAVE
        SendMessage_(GadgetID(0), #EM_SETSEL, 0, 0)
        IsTextSelected = #False
    CompilerEndIf
  EndSelect
ForEver
Zach
Addict
Addict
Posts: 1675
Joined: Sun Dec 12, 2010 12:36 am
Location: Somewhere in the midwest
Contact:

Re: Is it possible to select text natively upon setting focu

Post by Zach »

Just wanted to point out, if the idea here is to use it on short entries to allow the user to "type over", effectively replace what they've typed with a correction, etc.

Then a simple cross-platform solution is to just delete the text in the string gadget, which can be done by sending a null string to the StringGadget upon focus. This can be done with SetGadgetText() obviously.

Although I admit, that having the text selected instead, can remove certain ambiguities in some situations, where the user might be confused about what just happened.
Foz
Addict
Addict
Posts: 1359
Joined: Tue Nov 13, 2007 12:42 pm
Location: Manchester, UK

Re: Is it possible to select text natively upon setting focu

Post by Foz »

Not only that, but the user may not *want* the data to be removed - for instance editing data, where it's mostly correct, but one field is wrong, it's easier to simply skip the fields that are correct and overtype the wrong field.

I use this a lot when dealing with sales agreements at work - 30+ numeric fields, and a few of them have changed.
Post Reply