Announcement

Collapse
No announcement yet.

Determine if text box has focus

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Determine if text box has focus

    When I click on a textbox, I need to determine if that textbox has focus. I am drawing a blank.

    John Tate

  • #2
    Hi, John!

    Use the API GetFocus.

    Comment


    • #3
      But, if you click on it, how can it NOT have focus (unless your code does something to change the focus)? Is that something you've seen happen?

      Or, are you just wanting to confirm that the click really did happen.

      Comment


      • #4
        https://docs.microsoft.com/en-us/win...ls/en-setfocus
        Code:
        CASE %WM_COMMAND
        
          SELECT CASE AS LONG CB.CTL
        
             CASE %TEXTBOX1
                SELECT CASE AS LONG CB.CTLMSG
                   CASE %EN_CHANGE    'typing
                   CASE %EN_SETFOCUS  'got focus
                END SELECT
        
             CASE %TEXTBOX2
          END SELECT
        https://duckduckgo.com instead of google

        Comment


        • #5
          MY bad! I have 9 textboxes each with different text. I need to know which one now has the focus after I click on it so I retrieve that text. with control get text. DDT does not have "get focus" as far a I can see.
          Thanks, Gary

          Comment


          • #6
            Hi John!

            With Mike's code, used for each TextBox, you can get the TextBox content without each time the TextBox gets focus. Something like this ...

            Code:
            Case %TextBox1 : If Cb.CtlMsg = %EN_SetFocus Then Control Get Text hDlg, %IDC_TextBox1 to MyTextVariable
            Case %TextBox2 : If Cb.CtlMsg = %EN_SetFocus Then Control Get Text hDlg, %IDC_TextBox2 to MyTextVariable
            ...
            Case %TextBox9 : If Cb.CtlMsg = %EN_SetFocus Then Control Get Text hDlg, %IDC_TextBox9 to MyTextVariable

            Comment


            • #7
              John,
              It occurred to me that if your user TABs to the textbox, do you want to capture the textbox content? If not, then GetFocus would let you capture the text on demand.

              Comment


              • #8
                Can also use a modeless dialog.
                Code:
                #DIM ALL        'modal.bas
                #UNIQUE VAR ON
                #INCLUDE ONCE "WIN32API.INC"
                %LABEL1          = 201
                %TEXTBOX1        = 301
                %TEXTBOX2        = 302
                '
                FUNCTION PBMAIN()
                  MyDialog %HWND_DESKTOP
                END FUNCTION
                '
                FUNCTION Pump1(hDlg AS DWORD) AS LONG
                  LOCAL msg AS TagMsg, k AS LONG
                  WHILE GetMessage(msg, %NULL, 0, 0)
                    SELECT CASE Msg.message
                      k = Msg.wParam
                      CASE %WM_SYSKEYDOWN 'ALT keys
                      CASE %WM_KEYDOWN
                        IF ISTRUE(LOWRD(GetKeyState(%VK_CONTROL)) AND &H8000) THEN    'control key pressed
                          IF k>64 AND k< 91 THEN
                            SetLabel hDlg, "CTRL " + STR$(k+32) + "/" + CHR$(k+32)
                          END IF
                        ELSEIF ISTRUE(LOWRD(GetKeyState(%VK_SHIFT)) AND &H8000) THEN  'shift and character
                          IF k>64 AND k< 91 THEN                                      'UPPER CASE A-Z
                             SetLabel hDlg, "Last character1 " + STR$(k+32) + "/" + CHR$(k+32)
                          END IF
                        ELSE
                           SELECT CASE k
                             CASE 9    :SetLabel hDlg, "TAB"
                             CASE 13   :SetLabel hDlg, "ENTER to TAB":Msg.wParam = 9
                             CASE ELSE :SetLabel hDlg, "Last character2 " + STR$(k) + "/" + CHR$(k)
                           END SELECT
                        END IF
                    END SELECT
                    IF IsDialogMessage(hDlg, Msg) = %FALSE THEN
                      TranslateMessage Msg
                      DispatchMessage Msg
                    END IF
                  LOOP WHILE IsWindow(hdlg)
                END FUNCTION
                '
                SUB SetLabel(hDlg AS DWORD, s AS STRING)
                  CONTROL SET TEXT hDlg,%LABEL1, s
                END SUB
                '
                FUNCTION MyDialog(BYVAL hParent AS DWORD) AS LONG
                  LOCAL hDlg   AS DWORD
                  DIALOG NEW hParent, "Test",200,100,200,100, %WS_OVERLAPPEDWINDOW TO hDlg
                  CONTROL ADD LABEL,   hDlg, %LABEL1,   "", 10, 10, 100, 12
                  CONTROL ADD TEXTBOX, hDlg, %TEXTBOX1, "", 10, 30, 100, 12
                  CONTROL ADD TEXTBOX, hDlg, %TEXTBOX2, "", 10, 50, 100, 12
                  DIALOG SHOW MODELESS hDlg CALL MyCallBack
                  Pump1 hDlg
                END FUNCTION
                '
                CALLBACK FUNCTION MyCallBack
                  SELECT CASE AS LONG CB.MSG
                    CASE %WM_INITDIALOG
                    CASE %WM_COMMAND
                      SELECT CASE AS LONG CB.CTL
                        CASE %TEXTBOX1
                          SELECT CASE AS LONG CB.CTLMSG
                            CASE %EN_CHANGE
                              DIALOG SET TEXT CB.HNDL, "TEXTBOX1 %EN_CHANGE"
                            CASE %EN_SETFOCUS
                              DIALOG SET TEXT CB.HNDL, "TEXTBOX1 SET FOCUS"
                          END SELECT
                        CASE %TEXTBOX2
                          SELECT CASE AS LONG CB.CTLMSG
                            CASE %EN_CHANGE
                              DIALOG SET TEXT CB.HNDL, "TEXTBOX2 %EN_CHANGE"
                            CASE %EN_SETFOCUS
                              DIALOG SET TEXT CB.HNDL, "TEXTBOX2 SET FOCUS"
                          END SELECT
                        CASE %IDOK
                          'handle Enter key here instead of in message loop (optional)
                          'IF GetDlgCtrlId(GetFocus) = %IDCANCEL THEN 'if exit button
                          '  DIALOG END CB.HNDL, 0 'whatever..
                          'ELSE 'else textbox - move to next
                          '  SetFocus GetNextDlgTabItem(CB.HNDL, GetFocus, 0)
                          'END IF
                      END SELECT
                    CASE %WM_CLOSE 'close before destroy
                    CASE %WM_DESTROY
                  END SELECT
                END FUNCTION
                https://duckduckgo.com instead of google

                Comment


                • #9
                  YES, that is what I need to do-capture the text in the textbox that has focus. I cannot find the GetFocus you speak of.

                  if textbox1 has focus, control get text cb.hndl ,%IDC_TEXTBOX TO VARIABLE$. We need a "has focus" method.

                  Comment


                  • #10
                    Thanks Mike. I see your code. MY problem is I am not changing or adding any text to the highlighted textbox, so there is no change to be noticed.

                    Comment


                    • #11
                      When a control gets focus there is a %WM_COMMAND with cb.ctl equal to the ID of the control and cb.ctlmsg is %EN_SETFOCUS. This is implemented in the callback in Mike's code, but you'll use CONTROL GET TEXT instead of DIALOG SET TEXT to retrieve text from the textbox.

                      ((%EN_SETFOCUS is a notification of getting focus, not a command to set the focus on that control))

                      Also see Help for CONTROL ADD TEXTBOX Remarks section, and :
                      https://docs.microsoft.com/en-us/win...ls/en-setfocus

                      Cheers,
                      Dale

                      Comment


                      • #12
                        Code:
                         CASE %TEXTBOX1
                        ....  
                         CASE %TEXTBOX2
                        Come on guys, what's with the repetitive code. You know better than that
                        Use a consecutive block of values for your textboxes and do it once.
                        Code:
                        ...
                        SELECT CASE AS LONG CB.CTL
                              ...
                            CASE %TEXTBOX1 TO %TEXTBOX9
                                 SELECT CASE AS LONG CB.CTLMSG
                                    CASE %EN_CHANGE
                                             .....
                                    CASE %EN_SETFOCUS
                                            Control Get Text CB.HNDL, CB.CTL to MyTextVariable
                                END SELECT
                        ...    
                        END SELECT
                        ...

                        Comment


                        • #13
                          I often use this kind of repetitive code in development because it is easy to add any coding particularity to any control. Clean up come after if needed.

                          Still, on the other hand, since John said that no change to the textbox is to be considered, why checking for EN_CHANGE?

                          Code:
                          %Textbox01 = 101??
                          %Textbox02 = 102??
                          ...
                          %Textbox09 = 109??
                          
                          ...
                             CASE %WM_COMMAND
                               SELECT CASE CB.CTL      
                                 CASE %Textbox01 TO %Textbox09
                                   IF CB.CTLMSG = %EN_SETFOCUS THEN
                                     LOCAL sText AS STRING
                                     CONTROL GET TEXT CB.HNDL, CB.CTL TO sText
                                     DIALOG SET TEXT CB.HNDL, sText 'For demo purpose
                                   END IF

                          Comment


                          • #14
                            What, ... better?

                            Well, for one thing it's easier to drop in what I did - ok, maybe not easier but certainly no more difficult.

                            Two, there may be a time when one of the textboxes is not meant to be captured. Easier to make that change by commenting out one of the multiple lines.

                            Three, if you're a novice, the multiple line version is easier to read and later understand if you have changes down the road.

                            Four, if you make a mistake and reorder the %IDC (as I have done in the past with Enum blocks) so that another control gets in the list, it's harder to troubleshoot.

                            Five, John did not say that a single variable would be used to capture the value. I made that up in my example. The multiline approach lets you use a different variable (array element, perhaps) for each textbox.

                            Six. John may already have substantial code that doesn't use sequential IDC values, where changing them all is a pain.

                            So, "better" is a bit premature!



                            Comment


                            • #15
                              Thanks to all. Here is what I have working.
                              When I click on the size I want, size box turn blue to make sure I know that is the one I selected.
                              Now as soon as that size looses focus, the size box returns to normal colors.
                              I use the "selectedstring" variable to post to a textbox to print labels.

                              So, thanks again for this teaching from you all. Even at age 84, I still learn relatively quickly.


                              Code:
                              SELECT CASE AS LONG CB.CTL
                                              CASE %IDC_VSIZE1 TO %IDC_VSIZE9
                              
                                                    CONTROL SET COLOR CB.HNDL,CB.CTL, %RGB_BLACK,%RGB_WHITE
                              
                                                  IF CB.CTLMSG = %EN_SETFOCUS THEN
                                                      CONTROL SET COLOR CB.HNDL,CB.CTL, %RGB_WHITE,%RGB_BLUE
                                                      CONTROL GET TEXT CB.HNDL, CB.CTL TO SELECTEDSTRING
                                                      END IF

                              Comment


                              • #16
                                Originally posted by John Tate View Post
                                Code:
                                SELECT CASE AS LONG CB.CTL
                                CASE %IDC_VSIZE1 TO %IDC_VSIZE9
                                
                                CONTROL SET COLOR CB.HNDL,CB.CTL, %RGB_BLACK,%RGB_WHITE
                                
                                IF CB.CTLMSG = %EN_SETFOCUS THEN
                                CONTROL SET COLOR CB.HNDL,CB.CTL, %RGB_WHITE,%RGB_BLUE
                                CONTROL GET TEXT CB.HNDL, CB.CTL TO SELECTEDSTRING
                                END IF
                                ISTM, that that won't reset any of the other size boxes unless they receive some sort of message.. I suspect you need:
                                Code:
                                SELECT CASE AS LONG CB.CTL
                                CASE %IDC_VSIZE1 TO %IDC_VSIZE9
                                    IF CB.CTLMSG = %EN_SETFOCUS THEN'
                                        FOR sb = %IDC_VSIZE1 TO %IDC_VSIZE9
                                             CONTROL SET COLOR CB.HNDL, sb, %RGB_BLACK,%RGB_WHITE
                                        NEXT  
                                        CONTROL SET COLOR CB.HNDL,CB.CTL, %RGB_WHITE,%RGB_BLUE
                                        CONTROL GET TEXT CB.HNDL, CB.CTL TO SELECTEDSTRING
                                    END IF
                                And I'd rather type that once, than nine times

                                Comment


                                • #17
                                  Good catch about turning focus indication off when another control gets focus.

                                  Try that with a CB.CTLMSG = %EN_KILLFOCUS, and only change to normal color one textbox having it's ID in CB.CTL.

                                  ((changing where focus is will generate (at least) 2 %WM_COMMANDs, one with %EN_SETFOCUS (for gaining control) and one %EN_KILLFOCUS (for losing control)((I do not know which first. Does it matter in this case? It will be too fast to see))

                                  Cheers,
                                  Dale

                                  Comment


                                  • #18
                                    Originally posted by Dale Yarker View Post
                                    Good catch about turning focus indication off when another control gets focus.

                                    Try that with a CB.CTLMSG = %EN_KILLFOCUS, and only change to normal color one textbox having it's ID in CB.CTL.

                                    ((changing where focus is will generate (at least) 2 %WM_COMMANDs, one with %EN_SETFOCUS (for gaining control) and one %EN_KILLFOCUS (for losing control)((I do not know which first. Does it matter in this case? It will be too fast to see))

                                    Cheers,
                                    That will revert the highlight to unselected sizebox colours as soon as focus goes anywhere else rather than retaining the highlight until another size is selected. I'd stick with only updating when another size box is selected.

                                    Comment


                                    • #19
                                      Yeap! Programmer's behavier choice. Thanks for pointing that out, 'cuz I didn't think of that possibility (wanting highlight to remain).

                                      Cheers,
                                      Dale

                                      Comment


                                      • #20
                                        Originally posted by John Tate View Post
                                        When I click on a textbox, I need to determine if that textbox has focus. I am drawing a blank.

                                        John Tate
                                        You can keep track of which one has focus, if needed.
                                        I used a STATIC here, but you could employ a DIALOG USER variable.
                                        Code:
                                        #COMPILE EXE
                                        #DIM ALL
                                        #DEBUG DISPLAY
                                        ENUM labels SINGULAR
                                            lbl_foc = 500
                                            txt_01
                                            txt_02
                                            txt_03
                                        END ENUM
                                        FUNCTION PBMAIN () AS LONG
                                            LOCAL hWin AS DWORD,  xitval AS LONG
                                            DIALOG NEW PIXELS, 0, "Who has focus", , , 300, 200, %WS_POPUP OR %WS_CAPTION OR %WS_SYSMENU TO hWin
                                            CONTROL ADD TEXTBOX, hWin, %txt_01, "Textbox 01", 5,  5, 290, 20
                                            CONTROL ADD TEXTBOX, hWin, %txt_02, "Textbox 02", 5, 35, 290, 20
                                            CONTROL ADD TEXTBOX, hWin, %txt_03, "Textbox 03", 5, 65, 290, 20
                                            CONTROL ADD LABEL, hWin, %lbl_foc, "Textbox 01 has focus.", 5, 95, 290, 15
                                            DIALOG SHOW MODAL hWin, CALL dlgproc() TO xitval
                                            FUNCTION = xitval
                                        END FUNCTION
                                        CALLBACK FUNCTION dlgproc() AS LONG
                                            STATIC WhoHasFocus AS LONG
                                            SELECT CASE CB.MSG
                                                CASE %WM_INITDIALOG
                                                    WhoHasFocus = %txt_01
                                                CASE %WM_COMMAND
                                                    SELECT CASE CB.CTL
                                                        CASE %txt_01 TO %txt_03
                                                            IF CB.CTLMSG = %EN_SETFOCUS THEN
                                                                WhoHasFocus = CB.CTL
                                                                CONTROL SET TEXT CB.HNDL, %lbl_foc, "Textbox" + STR$(WhoHasFocus - %lbl_foc) + " has focus."
                                                            END IF
                                                    END SELECT
                                            END SELECT
                                        END FUNCTION
                                        The world is strange and wonderful.*
                                        I reserve the right to be horrifically wrong.
                                        Please maintain a safe following distance.
                                        *wonderful sold separately.

                                        Comment

                                        Working...
                                        X