Jump to content
Sign in to follow this  
Erion

How to position the cursor in a multi-line edit

Recommended Posts

Erion

Hello,

I'm wondering, how to move the cursor in a multi line edit field?

It is possible to set the selection via control messages, but that only applies to the current selection, and not the position of the cursor.

E.g. if I set it to the first character by specifying

GUICtrlSendMsg($handle, $EM_SetSel, 1, 0)

as soon as the cursor moves, it jumps back to the end of the text (i.e. if the UDLR arrows are pressed).

If anyone could enlighten me what I'm doing wrong, or whether there's a way to accomplish this, I'd invite him/her over for a virtual beer ;)

Erion

Share this post


Link to post
Share on other sites
Habland0

This example script jumps the caret to an arbitrary position in the text and inserts a string.

#include <GuiEdit.au3>
#include <GuiStatusBar.au3>
#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>

_Main()

Func _Main()
    Local $hEdit, $hGUI

    ; Create GUI
    $hGUI = GUICreate("Edit Set Sel", 400, 300)
    $hEdit = GUICtrlCreateEdit("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", 2, 2, 394, 268, BitOR($ES_WANTRETURN, $WS_VSCROLL))

    GUISetState()

    Sleep(3000)
    _GUICtrlEdit_SetSel($hEdit, 158, 158)
    Sleep(3000)
    _GUICtrlEdit_InsertText($hEdit, " HELLO ", 60)
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
    GUIDelete()
EndFunc   ;==>_Main

Share this post


Link to post
Share on other sites
Erion

Hi,

Thank you very much for the code.

In this example, if you press any arrow keys where the selection is supposed to position the cursor it also jumps back to the end of the text.

I'm guessing that the Insert function, which replaces the current selection with the text you specify works according to the selection (i.e. what is selected), but that does not seem to move the cursor along. If it would, the cursor'd have ended up near the selection, depending on which arrow key you pressed. E.g. one char right, one line down, etc.

Basically, I want the cursor to be at the exact beginning (i.e. before the first character).

Erion

Share this post


Link to post
Share on other sites
Habland0

In this example, if you press any arrow keys where the selection is supposed to position the cursor it also jumps back to the end of the text.

This is what I have trouble with replicating. When I execute this line on the text in my first example:

_GUICtrlEdit_SetSel($hEdit, 158, 158)

The caret is positioned before the letter "b". If I then press the left arrow key, the caret jumps to "a", whilst the right arrow key positions the caret in front of "c", just as you would expect.

The same with:

_GUICtrlEdit_InsertText($hEdit, " HELLO ", 60)

This places the caret after the inserted text (" HELLO ").

If you want to move it in front of the inserted text, simply execute another SetSel like this:

_GUICtrlEdit_InsertText($hEdit, " HELLO ", 60)
_GUICtrlEdit_SetSel($hEdit, 60, 60)

Can you confirm that this behaviour is the same at your end? Because in none of the cases described above does the caret ever jump to the end of the text when I'm using the arrow keys to navigate.

Share this post


Link to post
Share on other sites
Erion

Hello,

It seems, despite my first attempt, that it works as expected after inserting some text.

However how would one set the cursor to the beginning of the edit field?

Erion

Share this post


Link to post
Share on other sites
Erion

Hello,

This is just some test code trying to accomplish the same.

#include <GuiEdit.au3>
#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
Global Const $BS_DEFPUSHBUTTON = 0x0001
Opt("GUIOnEventMode", 0)
Local $sButton

Opt("WinWaitDelay"     ,  10)       ;  speeds up WinMove
Opt("GuiResizeMode"    , 802)   ;  controls will never move when window is resized
Opt("GUICoordMode",1)
Opt("GUIDataSeparatorChar", "|")
GUICreate("test")
Local $vIdHelp = GUICtrlCreateEdit("test", -1, -1, 400, 400, BitOr($GUI_SS_Default_Edit, $ES_ReadOnly, $WS_TabStop, $WS_VSCROLL))

Local $vIdClose = GUICtrlCreateButton("test", -1, -1, -1, -1, -1, $BS_DEFPUSHBUTTON)

GUICtrlSendMsg($vIdHelp, $EM_SetSel, 0, 0)
GUISetState()

While 1

$msg = GUIGetMsg()
Switch $msg
Case $vIdClose
ExitLoop
Case $GUI_EVENT_CLOSE 
ExitLoop
EndSwitch
WEnd

Both the previously posted code and this one works incorrectly, i.e. the cursor jumps to the end.

Erion

Share this post


Link to post
Share on other sites
Yashied

Maybe the following function will be useful for you.

#Include <GUIEdit.au3>
#Include <ScrollBarConstants.au3>
#Include <WindowsConstants.au3>

$sFile = RegRead('HKLM\SOFTWARE\AutoIt v3\AutoIt', 'InstallDir') & '\Include\Constants.au3'

GUICreate('MyGUI', 400, 295)
$Edit = GUICtrlCreateEdit('', 10, 10, 380, 275, BitOR($ES_WANTRETURN, $WS_VSCROLL, $WS_HSCROLL))
GUICtrlSetFont(-1, Default, Default, Default, 'Courier New')
GUISetState()

_GUICtrlEdit_SetText($Edit, FileRead($sFile))
_GUICtrlEdit_SetPos($Edit, 75, 28)

Do
Until GUIGetMsg() = -3

; #FUNCTION# ====================================================================================================================
; Name...........: _GUICtrlEdit_SetPos
; Description....: Sets the caret to the specified line and column.
; Syntax.........: _GUICtrlEdit_SetPos ( $hWnd, $iLine [, $iColumn] )
; Parameters.....: $hWnd    - Handle or identifier (controlID) to the control.
;                  $iLine   - The zero-based index of the line on which must set the caret. If this parameter is (-1),
;                             the caret will be set on the last line.
;                  $iColumn - The zero-based index of the column on which must set the caret. If this parameter is (-1),
;                             the caret will be set at the end of the specified line. Default is 0.
; Return values..: Success  - 1.
;                  Failure  - 0 and sets the @error flag to non-zero.
; Author.........: Yashied
; Modified.......:
; Remarks........: None
; Related........: _GUICtrlEdit_Scroll(), _GUICtrlEdit_SetSel()
; Link...........: None
; Example........: Yes
; ===============================================================================================================================

Func _GUICtrlEdit_SetPos($hWnd, $iLine, $iColumn = 0)

    If Not IsHWnd($hWnd) Then
        $hWnd = GUICtrlGetHandle($hWnd)
        If $hWnd = 0 Then
            Return SetError(1, 0, 0)
        EndIf
    EndIf

    Local $Lenght, $Num = 0, $Count = _GUICtrlEdit_GetLineCount($hWnd)

    If $iLine > $Count - 1 Then
        $Num = _GUICtrlEdit_GetTextLen($hWnd)
    Else
        If $iLine < 0 Then
            $iLine = $Count - 1
        EndIf
        For $i = 0 To $iLine - 1
            $Num += _GUICtrlEdit_LineLength($hWnd, $i) + 2 ; + @CR + @LF
        Next
        $Lenght = _GUICtrlEdit_LineLength($hWnd, $iLine)
        If ($iColumn < 0) Or ($iColumn > $Lenght) Then
            $iColumn = $Lenght
        EndIf
        $Num += $iColumn
    EndIf
    _GUICtrlEdit_SetSel($hWnd, $Num, $Num)
    _GUICtrlEdit_Scroll($hWnd, $SB_SCROLLCARET)
    Return 1
EndFunc   ;==>_GUICtrlEdit_SetPos

Share this post


Link to post
Share on other sites
Erion

Hello,

Thank you very much for the function.

In the example it works wonderfully, but in the code I posted earlier it also fails.

Ah, the merits of scripting... ;)

Erion

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×