qwert Posted March 6, 2016 Share Posted March 6, 2016 In working with multi-line rich text controls, I've found it difficult to navigate to individual lines and to characters within lines. As an example, consider the following GUI. 1. Is there a better method to navigate to the home position? 2. Is there a better way to navigate to the next line? expandcollapse popup; ; Insert Line Numbers ; #include <GuiRichEdit.au3> #include <GuiConstantsEx.au3> #include <WindowsConstants.au3> $text = "This is an example" & @CRLF & "of a five-line rich" & @CRLF & "text control ... to which" & @CRLF & "I would like to add" & @CRLF & "line number prefixes." $hGUI = GUICreate("Sample RichEdit", 360, 220) GUISetFont(12) $hRichEdit = _GUICtrlRichEdit_Create($hGUI, $text, 10, 10, 230, 200, BitOR($WS_HSCROLL, $ES_AUTOVSCROLL, $ES_MULTILINE, $WS_VSCROLL)) _GUICtrlRichEdit_SetSel($hRichEdit, 0, -1) _GUICtrlRichEdit_SetFont($hRichEdit, 12) _GUICtrlRichEdit_SetSel($hRichEdit, -1, -1) ; IS THERE A BETTER WAY TO NAVIGATE TO THE HOME POSITION? _GUICtrlRichEdit_GotoCharPos($hRichEdit, 0) $Button = GUICtrlCreateButton("Insert Nums", 250, 40, 100, 30) GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE _GUICtrlRichEdit_Destroy($hRichEdit) GUIDelete() ExitLoop Case $Button _InsertNums() EndSwitch WEnd Func _InsertNums() Local $lines = _GUICtrlRichEdit_GetLineCount($hRichEdit) _GUICtrlRichEdit_GotoCharPos($hRichEdit, 0) For $i = 1 to $lines Step 1 _GUICtrlRichEdit_InsertText($hRichEdit, "Line " & $i & ": ") ; _GUICtrlRichEdit_ScrollLines ($hRichEdit, 1) ControlSend($hGui, "", $hRichEdit, "{DOWN}") ; IS THERE A BETTER WAY TO NAVIGATE TO THE NEXT LINE? ControlSend($hGui, "", $hRichEdit, "{HOME}") Next EndFunc Thanks in advance for any suggestions. Link to comment Share on other sites More sharing options...
sukendn Posted March 6, 2016 Share Posted March 6, 2016 Honestly I only know about autoit 20 days . After 1 time tinkering , it's first product , so I want to complete it . But knowledge is limited, can not be done Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 6, 2016 Share Posted March 6, 2016 (edited) Try this. I don't know of a better way to select to the end of the rich edit, SetSel is always what I've done. As for your _InsertNums, you use _GUICtrlRichEdit_GetFirstCharPosOnLIne to get the insert point. #include <GuiRichEdit.au3> #include <GuiConstantsEx.au3> #include <WindowsConstants.au3> $text = "This is an example" & @CRLF & "of a five-line rich" & @CRLF & "text control ... to which" & @CRLF & "I would like to add" & @CRLF & "line number prefixes." $hGUI = GUICreate("Sample RichEdit", 360, 220) GUISetFont(12) $hRichEdit = _GUICtrlRichEdit_Create($hGUI, $text, 10, 10, 230, 200, BitOR($WS_HSCROLL, $ES_AUTOVSCROLL, $ES_MULTILINE, $WS_VSCROLL)) _GUICtrlRichEdit_SetSel($hRichEdit, 0, -1) _GUICtrlRichEdit_SetFont($hRichEdit, 12) _GUICtrlRichEdit_SetSel($hRichEdit, -1, -1) ; IS THERE A BETTER WAY TO NAVIGATE TO THE HOME POSITION? _GUICtrlRichEdit_GotoCharPos($hRichEdit, 0) $Button = GUICtrlCreateButton("Insert Nums", 250, 40, 100, 30) GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE _GUICtrlRichEdit_Destroy($hRichEdit) GUIDelete() ExitLoop Case $Button _InsertNums() EndSwitch WEnd Func _InsertNums() Local $lines = _GUICtrlRichEdit_GetLineCount($hRichEdit) For $i = 1 To $lines Step 1 _GUICtrlRichEdit_GotoCharPos($hRichEdit, _GUICtrlRichEdit_GetFirstCharPosOnLine($hRichEdit, $i)) _GUICtrlRichEdit_InsertText($hRichEdit, "Line " & $i & ": ") Next EndFunc ;==>_InsertNums Edited March 6, 2016 by InunoTaishou Link to comment Share on other sites More sharing options...
qwert Posted March 6, 2016 Author Share Posted March 6, 2016 Quote _GUICtrlRichEdit_GotoCharPos($hRichEdit, _GUICtrlRichEdit_GetFirstCharPosOnLine($hRichEdit, $i)) Yes, that works ... and I like it much better than the ControlSend's. In the future, maybe a UDF can provide some basic navigation, like "GoToNextLine". Thanks for your help with this. Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 6, 2016 Share Posted March 6, 2016 You mean, something like this? expandcollapse popupFunc _GUICtrlRichEdit_GoToNextLine($hWnd, $iSelPoint = -1, Const $bMoveToEnd = True) Local $iCpFirst = 0 Local $iCurrentLine = 0 Local $iCpNextLine = 0 Local $aGetSel Local $sTextInRange = "" Local $sTextInCurrentLine = "" Local $sTextInNextLine = "" Local $iRangeLength = 0 Local $iCurrentLineLength = 0 Local $iNextLineLength = 0 Local $iLineCount = _GUICtrlRichEdit_GetLineCount($hWnd) If (@error) Then Return SetError(@error, 0, False) $iCpFirst = _GUICtrlRichEdit_GetFirstCharPosOnLine($hWnd) If (@error) Then Return SetError(@error, 0, False) $iCurrentLine = _GUICtrlRichEdit_GetLineNumberFromCharPos($hWnd, $iCpFirst) If (@error) Then Return SetError(@error, 0, False) If ($iLineCount < $iCurrentLine + 1) Then Return ($bMoveToEnd ? _GUICtrlRichEdit_SetSel($hWnd, -1, -1) : _GUICtrlRichEdit_GotoCharPos($hWnd, $iCpFirst)) $iCpNextLine = _GUICtrlRichEdit_GetFirstCharPosOnLine($hWnd, $iCurrentLine + 1) If (@error) Then Return SetError(@error, 0, False) If ($iSelPoint = -1) Then $aGetSel = _GUICtrlRichEdit_GetSel($hWnd) If (@error) Then Return SetError(@error, 0, False) If ($aGetSel[1] > 0 And $iCpFirst <> $aGetSel[1]) Then $sTextInRange = _GUICtrlRichEdit_GetTextInRange($hWnd, $iCpFirst, $aGetSel[1]) If (@error) Then Return SetError(@error, 0, False) $sTextInCurrentLine = _GUICtrlRichEdit_GetTextInLine($hWnd, $iCurrentLine) If (@error) Then Return SetError(@error, 0, False) $sTextInNextLine = _GUICtrlRichEdit_GetTextInLine($hWnd, $iCurrentLine + 1) If (@error) Then Return SetError(@error, 0, False) EndIf $iRangeLength = StringLen($sTextInRange) $iCurrentLineLength = StringLen($sTextInCurrentLine) $iNextLineLength = StringLen($sTextInNextLine) If ($iRangeLength = $iCurrentLineLength) Then $iSelPoint = $iNextLineLength ElseIf ($iRangeLength > $iNextLineLength) Then $iSelPoint = $iNextLineLength ElseIf ($iRangeLength <= $iNextLineLength) Then $iSelPoint = $iRangeLength Else $iSelPoint = 0 EndIf EndIf Return _GUICtrlRichEdit_GotoCharPos($hWnd, $iCpNextLine + $iSelPoint) EndFunc ;==>_GUICtrlRichEdit_GoToNextLine Using -1 for the $iSelPoint will make the select point like if you had used the {Down} arrow. Using 0 for the $iSelPoint will move the selection to the beginning of the next line. Upon reaching the last line, calling GoToNextLine again will move the selection to the very end (this is not something RichEdit does but a lot of other editors will move the selection to the end of the line when you press {Down} on the last line.) If you don't want it to move the selection to the end then you can use False for the first parameter. Link to comment Share on other sites More sharing options...
qwert Posted March 7, 2016 Author Share Posted March 7, 2016 (edited) That is an excellent function ... and operates just as you said. It certainly fills the need I have at the moment. That said—and this is in no way meant to take away from what you've done—would you consider extending it to provide all line-level navigation? ... First Line ... Last Line ... Previous Line ... (and a specific line, of course) ... and all using the character position params you've defined. I ask because you obviously have a good handle on the RichEdit function set. As I stated in my original post, navigating rich edits has been a problem every time I've worked with them. But in any event, thanks for providing the function. It's a great benefit to have it. Edited March 7, 2016 by qwert Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 7, 2016 Share Posted March 7, 2016 Well I did have the free time, I'm sure it'll be useful for others as well. Plus, RichEdit is my favorite thing to play with. Changed it a little bit but it still works the same. You can use the $iCharPos to set where to go to on the line you're moving to. If it's -2 then it's treated the same way as using your {Up} and {Down} arrow keys in the edit, using -1 will move to the end of the line, and using 0 will move to the beginning of the line. Think of it the same way as _GUICtrlRichEdit_GoToCharPos except you can specify what line to move to. expandcollapse popup#include <GuiRichEdit.au3> #include <GuiConstantsEx.au3> #include <WindowsConstants.au3> Global Const $sText = "This is a new example" & @CRLF & "using a richedit control with" & @CRLF & "a few extra navigation" & @CRLF & "functions. Allowing you to" & @CRLF & "navigate through a richedit" & @CRLF & "control!" Global $hGUI = GUICreate("Sample RichEdit", 396, 232) Global $hRichEdit = _GUICtrlRichEdit_Create($hGUI, $sText, 8, 8, 256, 192, BitOR($WS_HSCROLL, $ES_AUTOVSCROLL, $ES_MULTILINE, $WS_VSCROLL)) Global $btnGoToFirst = GUICtrlCreateButton("Go To First Line", 264, 8, 96, 24) Global $btnPrevLine = GUICtrlCreateButton("Go To Prev Line", 264, 36, 96, 24) Global $btnGoToLine = GUICtrlCreateButton("Go To Line", 264, 64, 96, 24) Global $inpLineNum = GUICtrlCreateInput(5, 364, 64, 24, 24) Global $btnNextLine = GUICtrlCreateButton("Go To Next Line", 264, 92, 96, 24) Global $btnGoToLast = GUICtrlCreateButton("Go To Last Line", 264, 120, 96, 24) Global $inpCharPos = GUICtrlCreateInput(-2, 364, 152, 24, 24) Global $lblOutput = GUICtrlCreateLabel("", 8, 200, 216, 32) GUICtrlCreateLabel("$iCharPos = ", 264, 152, 96, 24) GUICtrlSetFont(-1, 10) _GUICtrlRichEdit_SetSel($hRichEdit, 0, -1) _GUICtrlRichEdit_SetFont($hRichEdit, 12, "Segoe UI") _GUICtrlRichEdit_GotoCharPos($hRichEdit, 0) GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE _GUICtrlRichEdit_Destroy($hRichEdit) GUIDelete() ExitLoop Case $btnGoToFirst _GUICtrlRichEdit_GoToFirstLine($hRichEdit, GUICtrlRead($inpCharPos)) GUICtrlSetData($lblOutput, "Error returned from _GUICtrlRichEdit_GoToFirstLine: " & @Error) Case $btnPrevLine _GUICtrlRichEdit_GoToPrevLine($hRichEdit, GUICtrlRead($inpCharPos)) GUICtrlSetData($lblOutput, "Error returned from _GUICtrlRichEdit_GoToPrevLine: " & @Error) Case $btnGoToLine _GUICtrlRichEdit_GoToLine($hRichEdit, GUICtrlRead($inpLineNum), GUICtrlRead($inpCharPos)) GUICtrlSetData($lblOutput, "Error returned from _GUICtrlRichEdit_GoToLine: " & @Error) Case $btnNextLine _GUICtrlRichEdit_GoToNextLine($hRichEdit, GUICtrlRead($inpCharPos)) GUICtrlSetData($lblOutput, "Error returned from _GUICtrlRichEdit_GoToNextLine: " & @Error) Case $btnGoToLast _GUICtrlRichEdit_GoToLastLine($hRichEdit, GUICtrlRead($inpCharPos)) GUICtrlSetData($lblOutput, "Error returned from _GUICtrlRichEdit_GoToLastLine: " & @Error) EndSwitch WEnd Func _GUICtrlRichEdit_GoToNextLine($hWnd, $iCharPos = -2, Const $bMoveToEnd = True) Local $iCpFirst = 0 Local $iCurrentLine = 0 Local $iCpNextLine = 0 Local $aGetSel Local $sTextInRange = "" Local $sTextInCurrentLine = "" Local $sTextInNextLine = "" Local $iRangeLength = 0 Local $iCurrentLineLength = 0 Local $iNextLineLength = 0 Local $iLineCount = _GUICtrlRichEdit_GetLineCount($hWnd) If (@Error) Then Return SetError(@Error, 0, False) $iCpFirst = _GUICtrlRichEdit_GetFirstCharPosOnLine($hWnd) If (@Error) Then Return SetError(@Error, 0, False) $iCurrentLine = _GUICtrlRichEdit_GetLineNumberFromCharPos($hWnd, $iCpFirst) If (@Error) Then Return SetError(@Error, 0, False) If ($iLineCount < $iCurrentLine + 1) Then Return ($bMoveToEnd ? _GUICtrlRichEdit_GotoCharPos($hWnd, -1) : _GUICtrlRichEdit_GotoCharPos($hWnd, $iCpFirst)) $iCpNextLine = _GUICtrlRichEdit_GetFirstCharPosOnLine($hWnd, $iCurrentLine + 1) If (@Error) Then Return SetError(@Error, 0, False) $aGetSel = _GUICtrlRichEdit_GetSel($hWnd) If (@Error) Then Return SetError(@Error, 0, False) If ($aGetSel[1] > 0 And $iCpFirst <> $aGetSel[1]) Then $sTextInRange = _GUICtrlRichEdit_GetTextInRange($hWnd, $iCpFirst, $aGetSel[1]) If (@Error) Then Return SetError(@Error, 0, False) EndIf $sTextInCurrentLine = _GUICtrlRichEdit_GetTextInLine($hWnd, $iCurrentLine) If (@Error) Then Return SetError(@Error, 0, False) $sTextInNextLine = _GUICtrlRichEdit_GetTextInLine($hWnd, $iCurrentLine + 1) If (@Error) Then Return SetError(@Error, 0, False) $iRangeLength = StringLen($sTextInRange) $iCurrentLineLength = StringLen($sTextInCurrentLine) $iNextLineLength = StringLen($sTextInNextLine) If ($iCharPos = -2) Then If ($iRangeLength = $iCurrentLineLength Or $iRangeLength > $iNextLineLength) Then $iCharPos = $iNextLineLength ElseIf ($iRangeLength <= $iNextLineLength) Then $iCharPos = $iRangeLength Else $iCharPos = 0 EndIf ElseIf (($iCharPos = -1) Or ($iCharPos > 0 And $iNextLineLength > $iCharPos)) Then $iCharPos = $iNextLineLength EndIf Return _GUICtrlRichEdit_GotoCharPos($hWnd, $iCpNextLine + $iCharPos) EndFunc ;==>_GUICtrlRichEdit_GoToNextLine Func _GUICtrlRichEdit_GoToPrevLine($hWnd, $iCharPos = -2, Const $bMoveToBegin = True) Local $iCpFirst = 0 Local $iCurrentLine = 0 Local $iCpPrevLine = 0 Local $aGetSel Local $sTextInRange = "" Local $sTextInCurrentLine = "" Local $sTextInPrevLine = "" Local $iRangeLength = 0 Local $iCurrentLineLength = 0 Local $iPrevLineLength = 0 Local $iLineCount = _GUICtrlRichEdit_GetLineCount($hWnd) If (@Error) Then Return SetError(@Error, 0, False) $aGetSel = _GUICtrlRichEdit_GetSel($hWnd) If (@Error) Then Return SetError(@Error, 0, False) $iCpFirst = _GUICtrlRichEdit_GetFirstCharPosOnLine($hWnd) If (@Error) Then Return SetError(@Error, 0, False) $iCurrentLine = _GUICtrlRichEdit_GetLineNumberFromCharPos($hWnd, $iCpFirst) If (@Error) Then Return SetError(@Error, 0, False) If ($iCurrentLine = 1) Then Return ($bMoveToBegin ? _GUICtrlRichEdit_GotoCharPos($hWnd, 0) : _GUICtrlRichEdit_GotoCharPos($hWnd, $aGetSel[1])) $iCpPrevLine = _GUICtrlRichEdit_GetFirstCharPosOnLine($hWnd, $iCurrentLine - 1) If (@Error) Then Return SetError(@Error, 0, False) If ($aGetSel[1] > 0 And $iCpFirst <> $aGetSel[1]) Then $sTextInRange = _GUICtrlRichEdit_GetTextInRange($hWnd, $iCpFirst, $aGetSel[1]) If (@Error) Then Return SetError(@Error, 0, False) EndIf $sTextInCurrentLine = _GUICtrlRichEdit_GetTextInLine($hWnd, $iCurrentLine) If (@Error) Then Return SetError(@Error, 0, False) $sTextInPrevLine = _GUICtrlRichEdit_GetTextInLine($hWnd, $iCurrentLine - 1) If (@Error) Then Return SetError(@Error, 0, False) $iRangeLength = StringLen($sTextInRange) $iCurrentLineLength = StringLen($sTextInCurrentLine) $iPrevLineLength = StringLen($sTextInPrevLine) If ($iCharPos = -2) Then If ($iRangeLength = $iCurrentLineLength Or $iRangeLength > $iPrevLineLength) Then $iCharPos = $iPrevLineLength ElseIf ($iRangeLength <= $iPrevLineLength) Then $iCharPos = $iRangeLength Else $iCharPos = 0 EndIf ElseIf (($iCharPos = -1) Or ($iCharPos > 0 And $iPrevLineLength > $iCharPos)) Then $iCharPos = $iPrevLineLength EndIf Return _GUICtrlRichEdit_GotoCharPos($hWnd, $iCpPrevLine + $iCharPos) EndFunc ;==>_GUICtrlRichEdit_GoToPrevLine Func _GUICtrlRichEdit_GoToFirstLine($hWnd, $iCharPos = -2, Const $bMoveToBegin = True) Local $bRet = _GUICtrlRichEdit_GoToLine($hWnd, 1, $iCharPos, $bMoveToBegin) Return (@Error ? SetError(@Error, 0, $bRet) : $bRet) EndFunc ;==>_GUICtrlRichEdit_GoToFirstLine Func _GUICtrlRichEdit_GoToLastLine($hWnd, $iCharPos = -2, Const $bMoveToEnd = True) Local $iLineCount = _GUICtrlRichEdit_GetLineCount($hWnd) If (@Error) Then Return SetError(@Error, 0, False) Local $bRet = _GUICtrlRichEdit_GoToLine($hWnd, $iLineCount, $iCharPos, $bMoveToEnd) Return (@Error ? SetError(@Error, 0, $bRet) : $bRet) EndFunc ;==>_GUICtrlRichEdit_GoToLastLine Func _GUICtrlRichEdit_GoToLine($hWnd, $iGoToLine, $iCharPos = -2, Const $bMoveToStartEnd = True) Local $iCpFirst = 0 Local $iCurrentLine = 0 Local $iCpGoToLine = 0 Local $aGetSel Local $sTextInRange = "" Local $sTextInCurrentLine = "" Local $sTextInGoToLine = "" Local $iRangeLength = 0 Local $iCurrentLineLength = 0 Local $iGoToLineLength = 0 Local $iLineCount If ($iGoToLine < 1) Then Return SetError(-1021, 0, False) $iLineCount = _GUICtrlRichEdit_GetLineCount($hWnd) If (@Error) Then Return SetError(@Error, 0, False) $aGetSel = _GUICtrlRichEdit_GetSel($hWnd) If (@Error) Then Return SetError(@Error, 0, False) $iCpFirst = _GUICtrlRichEdit_GetFirstCharPosOnLine($hWnd) If (@Error) Then Return SetError(@Error, 0, False) $iCurrentLine = _GUICtrlRichEdit_GetLineNumberFromCharPos($hWnd, $iCpFirst) If (@Error) Then Return SetError(@Error, 0, False) If ($iGoToLine >= $iLineCount) Then $iGoToLine = $iLineCount If ($iGoToLine = $iLineCount And $iCurrentLine = $iLineCount) Then Return ($bMoveToStartEnd ? _GUICtrlRichEdit_GotoCharPos($hWnd, -1) : _GUICtrlRichEdit_GotoCharPos($hWnd, $aGetSel[1])) If ($iGoToLine = 1 And $iCurrentLine = 1) Then Return ($bMoveToStartEnd ? _GUICtrlRichEdit_GotoCharPos($hWnd, 0) : _GUICtrlRichEdit_GotoCharPos($hWnd, $aGetSel[1])) $iCpGoToLine = _GUICtrlRichEdit_GetFirstCharPosOnLine($hWnd, $iGoToLine) If (@Error) Then Return SetError(@Error, 0, False) If ($aGetSel[1] > 0 And $iCpFirst <> $aGetSel[1]) Then $sTextInRange = _GUICtrlRichEdit_GetTextInRange($hWnd, $iCpFirst, $aGetSel[1]) If (@Error) Then Return SetError(@Error, 0, False) EndIf $sTextInCurrentLine = _GUICtrlRichEdit_GetTextInLine($hWnd, $iCurrentLine) If (@Error) Then Return SetError(@Error, 0, False) $sTextInGoToLine = _GUICtrlRichEdit_GetTextInLine($hWnd, $iGoToLine) If (@Error) Then Return SetError(@Error, 0, False) $iRangeLength = StringLen($sTextInRange) $iCurrentLineLength = StringLen($sTextInCurrentLine) $iGoToLineLength = StringLen($sTextInGoToLine) If ($iCharPos = -2) Then If ($iRangeLength = $iCurrentLineLength Or $iRangeLength > $iGoToLineLength) Then $iCharPos = $iGoToLineLength ElseIf ($iRangeLength <= $iGoToLineLength) Then $iCharPos = $iRangeLength Else $iCharPos = 0 EndIf ElseIf (($iCharPos = -1) Or ($iCharPos > 0 And $iGoToLineLength > $iCharPos)) Then $iCharPos = $iGoToLineLength EndIf Return _GUICtrlRichEdit_GotoCharPos($hWnd, $iCpGoToLine + $iCharPos) EndFunc ;==>_GUICtrlRichEdit_GoToLine Link to comment Share on other sites More sharing options...
qwert Posted March 7, 2016 Author Share Posted March 7, 2016 Thank you. These are great functions. RichEdit navigation now makes sense. The only tiny thing I found was that the end-of-line condition is "sticky". IOW, on line 5, if you have the cursor between the t and e of "navigate" and go next line, previous line, the cursor stays at that character position. But if you change it to just after the e in "navigate" and do the same next/prev actions, the cursor changes to end-of-line mode. You might want to have it go straight above (above the "!"), if that's possible. Or maybe it's fine, as is. I can see a case for both. Nonetheless, after a few days of testing, this should be formalized to a UDF! Anyone working with multi-line richedit controls should use it. Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 7, 2016 Share Posted March 7, 2016 I see what you mean. It could be fixed but it looks like it would require a global variable to detect if the position is being moved from end to end or if the position was moving from not at the end of a line to the end of the line of the line moving to. The reason it does that is because "navigate" is 8 chars long, and "control!" is 8 chars long, so it moves it to the end. When you go the next position using -2 for the $iCharPos parameter then it's recognizing that the caret (the blinking cursor) is at the end of the line, so it needs to move to the end. If you want to preserve where the caret is per line then store the current position on the line yourself and use that for the $iCharPos parameter when you need it $iCpFirst = _GUICtrlRichEdit_GetFirstCharPosOnLine($hWnd) If (@Error) Then Return SetError(@Error, 0, False) $aGetSel = _GUICtrlRichEdit_GetSel($hWnd) If (@Error) Then Return SetError(@Error, 0, False) If ($aGetSel[1] > 0 And $iCpFirst <> $aGetSel[1]) Then $sTextInRange = _GUICtrlRichEdit_GetTextInRange($hWnd, $iCpFirst, $aGetSel[1]) If (@Error) Then Return SetError(@Error, 0, False) EndIf $iRangeLength = StringLen($sTextInRange) You could make a function with this to save where the $iCharPos should be when you want to start moving. It wouldn't matter if the line you're going to is shorter than the saved position because I made it so that if the value you pass in $iCharPos is greater than the line length you're moving to, it will default to the end of that line. A lot of this code can be shortened too, since each function does the same thing, just different lines. I'll probably end up re-doing it tomorrow to clean it up and store all the repetitive stuff in a function. Looking at it again, I think the other thing I didn't account for is if the $iCharPos is < -2, which will move the caret one line behind where you want to go, so I'll probably fix that too. Link to comment Share on other sites More sharing options...
qwert Posted March 7, 2016 Author Share Posted March 7, 2016 8 hours ago, InunoTaishou said: When you go the next position using -2 for the $iCharPos parameter then it's recognizing that the caret (the blinking cursor) is at the end of the line, so it needs to move to the end. Wouldn't that be appropriate for -1, instead? That way, -2 would be saying "work at the character level ... and -1 would be "work at the line level". That's just my thought. Internally, it may need to be different. Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 7, 2016 Share Posted March 7, 2016 -1 will move it to the end regardless of the length of the line you're moving to. -2 will just check to make sure that the line you're moving to is at least as long as where the caret is for the line it's currently on. Since the caret is at the end of "navigate" (8 chars long) and it's trying to move to the next line, which is only the word "control!" (8 chars long), it sees that it can move to that line at the correct character position--the end of the line. Link to comment Share on other sites More sharing options...
qwert Posted March 7, 2016 Author Share Posted March 7, 2016 Just as a test, in _GUICtrlRichEdit_GoToPrevLine, I changed: If ($iCharPos = -2) Then If ($iRangeLength = $iCurrentLineLength Or $iRangeLength > $iPrevLineLength) Then To this: If ($iCharPos = -2) Then If ($iRangeLength > $iPrevLineLength) Then It causes the cursor to move directly above if there is an "above" ... otherwise it moves to the end of the previous line. I may be oversimplifying, but this gives the behavior I was talking about. It's just a suggestion, but I think it makes movements more intuitive. Let me know if there are other considerations. Link to comment Share on other sites More sharing options...
InunoTaishou Posted March 7, 2016 Share Posted March 7, 2016 Ah yes, you're right. I was thinking about that this morning when I was driving. I have adjusted it. Now it should work as desired. Also shortened it and threw some of the repetitive stuff in a separate functions. Spoiler Quote -2 Works the same as {Up} and {Down} arrows. -1 Moves caret to the end of specified line. 0 Moves caret to the beginning of specified line. @Error -1021 is line requested is <1 or > the line count. @Error -1022 is the $iCharPos used is < -2 expandcollapse popup#include <GuiRichEdit.au3> #include <GuiConstantsEx.au3> #include <WindowsConstants.au3> Global Const $sText = "This is a new example" & @CRLF & "using a richedit control with" & @CRLF & "a few extra navigation" & @CRLF & "functions. Allowing you to" & @CRLF & "navigate through a richedit" & @CRLF & "control!" Global $hGUI = GUICreate("Sample RichEdit", 396, 232) Global $hRichEdit = _GUICtrlRichEdit_Create($hGUI, $sText, 8, 8, 256, 192, BitOR($WS_HSCROLL, $ES_AUTOVSCROLL, $ES_MULTILINE, $WS_VSCROLL)) Global $btnGoToFirst = GUICtrlCreateButton("Go To First Line", 264, 8, 96, 24) Global $btnPrevLine = GUICtrlCreateButton("Go To Prev Line", 264, 36, 96, 24) Global $btnGoToLine = GUICtrlCreateButton("Go To Line", 264, 64, 96, 24) Global $inpLineNum = GUICtrlCreateInput(5, 364, 64, 24, 24) Global $btnNextLine = GUICtrlCreateButton("Go To Next Line", 264, 92, 96, 24) Global $btnGoToLast = GUICtrlCreateButton("Go To Last Line", 264, 120, 96, 24) Global $inpCharPos = GUICtrlCreateInput(-2, 364, 152, 24, 24) Global $lblOutput = GUICtrlCreateLabel("", 8, 200, 216, 32) GUICtrlCreateLabel("$iCharPos = ", 264, 152, 96, 24) GUICtrlSetFont(-1, 10) _GUICtrlRichEdit_SetSel($hRichEdit, 0, -1) _GUICtrlRichEdit_SetFont($hRichEdit, 12, "Segoe UI") _GUICtrlRichEdit_GotoCharPos($hRichEdit, 0) GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE _GUICtrlRichEdit_Destroy($hRichEdit) GUIDelete() ExitLoop Case $btnGoToFirst _GUICtrlRichEdit_GoToFirstLine($hRichEdit, GUICtrlRead($inpCharPos)) GUICtrlSetData($lblOutput, "Error returned from _GUICtrlRichEdit_GoToFirstLine: " & @error) Case $btnPrevLine _GUICtrlRichEdit_GoToPrevLine($hRichEdit, GUICtrlRead($inpCharPos)) GUICtrlSetData($lblOutput, "Error returned from _GUICtrlRichEdit_GoToPrevLine: " & @error) Case $btnGoToLine _GUICtrlRichEdit_GoToLine($hRichEdit, GUICtrlRead($inpLineNum), GUICtrlRead($inpCharPos)) GUICtrlSetData($lblOutput, "Error returned from _GUICtrlRichEdit_GoToLine: " & @error) Case $btnNextLine _GUICtrlRichEdit_GoToNextLine($hRichEdit, GUICtrlRead($inpCharPos)) GUICtrlSetData($lblOutput, "Error returned from _GUICtrlRichEdit_GoToNextLine: " & @error) Case $btnGoToLast _GUICtrlRichEdit_GoToLastLine($hRichEdit, GUICtrlRead($inpCharPos)) GUICtrlSetData($lblOutput, "Error returned from _GUICtrlRichEdit_GoToLastLine: " & @error) EndSwitch WEnd Func _GUICtrlRichEdit_GoToNextLine($hWnd, $iCharPos = -2, Const $bMoveToEnd = True) Local $iCpFirst = 0 Local $iCurrentLine = 0 Local $iCpNextLine = 0 Local $iLineCount = _GUICtrlRichEdit_GetLineCount($hWnd) If (@error) Then Return SetError(@error, 0, False) $iCurrentLine = _GUICtrlRichEdit_GetCurrentLine($hWnd, $iCpFirst) If (@error) Then Return SetError(@error, 0, False) If ($iLineCount < $iCurrentLine + 1) Then Return ($bMoveToEnd ? _GUICtrlRichEdit_GotoCharPos($hWnd, -1) : _GUICtrlRichEdit_GotoCharPos($hWnd, $iCpFirst)) $iCpNextLine = _GUICtrlRichEdit_GetFirstCharPosOnLine($hWnd, $iCurrentLine + 1) If (@error) Then Return SetError(@error, 0, False) $iCharPos = _GUICtrlRichEdit_GetCharPosForLine($hWnd, $iCharPos, $iCurrentLine + 1) If (@error) Then Return SetError(@error, 0, False) Return _GUICtrlRichEdit_GotoCharPos($hWnd, $iCpNextLine + $iCharPos) EndFunc ;==>_GUICtrlRichEdit_GoToNextLine Func _GUICtrlRichEdit_GoToPrevLine($hWnd, $iCharPos = -2, Const $bMoveToBegin = True) Local $iCpFirst = 0 Local $iCurrentLine = 0 Local $iCpPrevLine = 0 Local $aGetSel $iCurrentLine = _GUICtrlRichEdit_GetCurrentLine($hWnd, $iCpFirst) If (@error) Then Return SetError(@error, 0, False) $aGetSel = _GUICtrlRichEdit_GetSel($hWnd) If (@error) Then Return SetError(@error, 0, False) If ($iCurrentLine = 1) Then Return ($bMoveToBegin ? _GUICtrlRichEdit_GotoCharPos($hWnd, 0) : _GUICtrlRichEdit_GotoCharPos($hWnd, $aGetSel[1])) $iCpPrevLine = _GUICtrlRichEdit_GetFirstCharPosOnLine($hWnd, $iCurrentLine - 1) If (@error) Then Return SetError(@error, 0, False) $iCharPos = _GUICtrlRichEdit_GetCharPosForLine($hWnd, $iCharPos, $iCurrentLine - 1) If (@error) Then Return SetError(@error, 0, False) Return _GUICtrlRichEdit_GotoCharPos($hWnd, $iCpPrevLine + $iCharPos) EndFunc ;==>_GUICtrlRichEdit_GoToPrevLine Func _GUICtrlRichEdit_GoToFirstLine($hWnd, $iCharPos = -2, Const $bMoveToBegin = True) Local $bRet = _GUICtrlRichEdit_GoToLine($hWnd, 1, $iCharPos, $bMoveToBegin) Return (@error ? SetError(@error, 0, $bRet) : $bRet) EndFunc ;==>_GUICtrlRichEdit_GoToFirstLine Func _GUICtrlRichEdit_GoToLastLine($hWnd, $iCharPos = -2, Const $bMoveToEnd = True) Local $iLineCount = _GUICtrlRichEdit_GetLineCount($hWnd) If (@error) Then Return SetError(@error, 0, False) Local $bRet = _GUICtrlRichEdit_GoToLine($hWnd, $iLineCount, $iCharPos, $bMoveToEnd) Return (@error ? SetError(@error, 0, $bRet) : $bRet) EndFunc ;==>_GUICtrlRichEdit_GoToLastLine Func _GUICtrlRichEdit_GoToLine($hWnd, $iGoToLine, $iCharPos = -2, Const $bMoveToStartEnd = True) Local $iCpFirst = 0 Local $iCurrentLine = 0 Local $iCpGoToLine = 0 Local $aGetSel Local $iLineCount = _GUICtrlRichEdit_GetLineCount($hWnd) If (@error) Then Return SetError(@error, 0, False) $iCurrentLine = _GUICtrlRichEdit_GetCurrentLine($hWnd, $iCpFirst) If (@error) Then Return SetError(@error, 0, False) $aGetSel = _GUICtrlRichEdit_GetSel($hWnd) If (@error) Then Return SetError(@error, 0, False) If ($iGoToLine = $iLineCount And $iCurrentLine = $iLineCount) Then Return ($bMoveToStartEnd ? _GUICtrlRichEdit_GotoCharPos($hWnd, -1) : _GUICtrlRichEdit_GotoCharPos($hWnd, $aGetSel[1])) If ($iGoToLine = 1 And $iCurrentLine = 1) Then Return ($bMoveToStartEnd ? _GUICtrlRichEdit_GotoCharPos($hWnd, 0) : _GUICtrlRichEdit_GotoCharPos($hWnd, $aGetSel[1])) $iCpGoToLine = _GUICtrlRichEdit_GetFirstCharPosOnLine($hWnd, $iGoToLine) If (@error) Then Return SetError(@error, 0, False) $iCharPos = _GUICtrlRichEdit_GetCharPosForLine($hWnd, $iCharPos, $iCurrentLine - 1) If (@error) Then Return SetError(@error, 0, False) Return _GUICtrlRichEdit_GotoCharPos($hWnd, $iCpGoToLine + $iCharPos) EndFunc ;==>_GUICtrlRichEdit_GoToLine Func _GUICtrlRichEdit_GetCharPosForLine($hWnd, $iCharPos, Const $iLine) Local $iCpFirst = 0 Local $iCurrentLine = 0 Local $iCpLine = 0 Local $aGetSel Local $sTextInRange = "" Local $sTextInCurrentLine = "" Local $sTextInLine = "" Local $iRangeLength = 0 Local $iCurrentLineLength = 0 Local $iLineLength = 0 Local $iLineCount = 0 $iLineCount = _GUICtrlRichEdit_GetLineCount($hWnd) If (@error) Then Return SetError(@error, 0, False) If ($iLine < 1 Or $iLine > $iLineCount) Then Return SetError(-1021, 0, False) $aGetSel = _GUICtrlRichEdit_GetSel($hWnd) If (@error) Then Return SetError(@error, 0, False) $iCurrentLine = _GUICtrlRichEdit_GetCurrentLine($hWnd, $iCpFirst) If ($iLine = $iCurrentLine) Then Return SetError(-1, 0, $iCharPos) $iCpLine = _GUICtrlRichEdit_GetFirstCharPosOnLine($hWnd, $iLine) If (@error) Then Return SetError(@error, 0, False) If ($aGetSel[1] > 0 And $iCpFirst <> $aGetSel[1]) Then $sTextInRange = _GUICtrlRichEdit_GetTextInRange($hWnd, $iCpFirst, $aGetSel[1]) If (@error) Then Return SetError(@error, 0, False) EndIf $sTextInCurrentLine = _GUICtrlRichEdit_GetTextInLine($hWnd, $iCurrentLine) If (@error) Then Return SetError(@error, 0, False) $sTextInLine = _GUICtrlRichEdit_GetTextInLine($hWnd, $iLine) If (@error) Then Return SetError(@error, 0, False) $iRangeLength = StringLen($sTextInRange) $iCurrentLineLength = StringLen($sTextInCurrentLine) $iLineLength = StringLen($sTextInLine) If ($iCharPos = -2) Then If ($iRangeLength > $iLineLength) Then $iCharPos = $iLineLength ElseIf ($iRangeLength <= $iLineLength) Then $iCharPos = $iRangeLength EndIf ElseIf ($iCharPos = -1) Then $iCharPos = $iLineLength ElseIf ($iCharPos > 0 And $iLineLength > $iCharPos) Then $iCharPos = $iLineLength EndIf Return $iCharPos EndFunc ;==>_GUICtrlRichEdit_GetCharPosForLine Func _GUICtrlRichEdit_GetCurrentLine($hWnd, ByRef $iCpFirst) $iCpFirst = _GUICtrlRichEdit_GetFirstCharPosOnLine($hWnd) If (@error) Then Return SetError(@error, 0, False) Return _GUICtrlRichEdit_GetLineNumberFromCharPos($hWnd, $iCpFirst) EndFunc ;==>_GUICtrlRichEdit_GetCurrentLine Link to comment Share on other sites More sharing options...
qwert Posted March 7, 2016 Author Share Posted March 7, 2016 Excellent. Five Stars from me! Thanks, again. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now