Announcement

Collapse
No announcement yet.

Position caret in text box

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

  • Position caret in text box

    I need to tab into a text box without any text being highlighted (no problem there) but also need to be able to
    place the caret in the text box to match the position it held the last time the text box lost the focus. I'm
    using the GetCaretPos and SetCaretPos API calls, and the caret seems to be get positioned properly when you
    re-enter the text box, but in reality it is not.

    My problem is demonstrated in the following code... when you execute it, use your keyboard or mouse to position
    the caret in the center of the text in the first text box and then press tab twice. Upon re-entering the first
    text box, the caret looks repositioned. However, use your left arrow key to move the caret and you will see that
    the caret was really at the right end of the text.
    Code:
    #COMPILE EXE
    #REGISTER NONE
    #INCLUDE "WIN32API.INC"
    
    
    CALLBACK FUNCTION DlgProc
       STATIC PT AS POINTAPI
    
       
       SELECT CASE CBMSG
       CASE %WM_COMMAND
          SELECT CASE CBCTLMSG
          CASE %EN_SETFOCUS
             ' Remove text selection highlight from text boxes
             CONTROL SEND CBHNDL, CBCTL, %EM_SETSEL, -1, -1
    
    
             SELECT CASE CBCTL
             CASE 100
                ' Attempt to position caret in Text Box 1
                SetCaretPos PT.x, PT.y
             END SELECT
    
             
          CASE %EN_KILLFOCUS
             SELECT CASE CBCTL
             CASE 100
                ' Remember caret position for Text Box 1
                GetCaretPos PT
             END SELECT
    
       
          END SELECT
       END SELECT
    END FUNCTION
    
    
    FUNCTION PBMAIN
       LOCAL hDlg AS LONG
       DIALOG NEW 0 ,"Caret Test",,, 200, 65, %WS_MINIMIZEBOX + %WS_SYSMENU TO hDlg
       CONTROL ADD TEXTBOX, hDlg, 100, "Text Box 1", 10, 10, 176, 12
       CONTROL ADD TEXTBOX, hDlg, 200, "Text Box 2", 10, 25, 176, 12
       DIALOG SHOW MODAL hDlg CALL DlgProc
    END FUNCTION
    Any Ideas?

    Timm

    [This message has been edited by Timm Motl (edited July 24, 2001).]
    mailto:[email protected]
    Tsunami Record Manager

  • #2
    I'm not at my DEV PC to test, but I see that you are not using FUNCTION=1 in your %EN_SETFOCUS notification handler.

    Without that, it seems likely that the default edit control handler is setting the selection immediately after your handler does it. Remember that returning zero indicates that your code did not actually "handle" the notification message. In most cases, your callback should set the return 1 if your code processes the message.

    I hope this helps!

    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>
    Lance
    mailto:[email protected]

    Comment


    • #3
      I think %EM_GET/SETSEL is better
      Code:
         #Compile Exe
         #Register None
         #Dim All
         #Include "WIN32API.INC"
      
         CallBack Function SuperEditProc
            Static OldProc As Long, OffsetWndExtra As Long
            If CbHndl = 0 Then OldProc = CbWparam: OffsetWndExtra = CbLparam: Exit Function
            Select Case CbMsg
               Case %WM_SETFOCUS
                  Static s As Dword, e As Dword, k As Long
                  s = GetWindowLong (CbHndl, OffsetWndExtra)
                  e = GetWindowLong (CbHndl, OffsetWndExtra + 4)
                  SendMessage CbHndl, %EM_SETSEL, s, e
               Case %WM_KILLFOCUS
                 SendMessage CbHndl, %EM_GETSEL, VarPtr(s), VarPtr(e)
                  SetWindowLong CbHndl, OffsetWndExtra, s
                  SetWindowLong CbHndl, OffsetWndExtra + 4, e
            End Select
            Function = CallWindowProc(OldProc, CbHndl, CbMsg, CbWparam, CbLparam)
         End Function
      
         Function CreateSuperClass(OldClassName As String, NewClassName As String, lpfnNewWndProc As Long, cbWndExtra As Long) As Long
            Local wc As WNDCLASSEX
            wc.cbSize = SizeOf(wc)
            If GetClassInfoEx(ByVal 0&, ByVal StrPtr(OldClassName), wc) Then
               CallWindowProc lpfnNewWndProc, 0, 0, wc.lpfnWndProc, wc.cbWndExtra
               wc.hInstance = GetModuleHandle(ByVal 0&)
               wc.lpszClassName = StrPtr(NewClassName)
               wc.lpfnWndProc = lpfnNewWndProc
               wc.cbWndExtra = wc.cbWndExtra + cbWndExtra
               Function = RegisterClassEx(wc)
            End If
         End Function
      
         Function PbMain
            If IsFalse(CreateSuperClass("EDIT", "SuperEdit", CodePtr(SuperEditProc), 8)) Then Exit Function
      
            Dim hDlg As Long
            Dialog New 0, "Test", , , 120, 160, %WS_CAPTION Or %WS_SYSMENU Or %WS_MAXIMIZEBOX To hDlg
            Control Add "SuperEdit", hDlg, 101, "", 10, 10, 100, 60, %WS_CHILD Or %WS_VISIBLE Or %WS_TABSTOP _
               Or %ES_MULTILINE Or %ES_WANTRETURN, %WS_EX_CLIENTEDGE
            Control Add "SuperEdit", hDlg, 102, "", 10, 80, 100, 60 , %WS_CHILD Or %WS_VISIBLE Or %WS_TABSTOP _
               Or %ES_MULTILINE Or %ES_WANTRETURN, %WS_EX_CLIENTEDGE
            Dialog Show Modal hDlg
      
         End Function

      ------------------
      E-MAIL: [email protected]

      Comment


      • #4
        Lance:

        Thanks for responding... didn't realize FUNCTION = 1 was required when handling these messages... WIN32.HLP
        says if processing WM_COMMAND you should return zero, and it doesn't say anything about a return value required
        for EN_SETFOCUS or EN_KILLFOCUS. I tried it anyway, but the behavior remained unchanged. Still puzzles me.


        Semen:

        Your superclassing example works great. Thanks for the assist.

        Timm
        mailto:[email protected]
        Tsunami Record Manager

        Comment

        Working...
        X