How to get the text cursor / caret position

Helpful script writing tricks and HowTo's
mythofechelon
Posts: 19
Joined: 20 Jun 2018, 05:03

How to get the text cursor / caret position

13 Nov 2020, 18:00

I have a need to get the text cursor / caret position in order to get the text to the left of it when renaming a file in File Explorer.

I researched this and found many others with the same requirement but no proper solution. For example: I eventually threw together the following workaround which did work but was very inelegant - it was so noticeably slow that I could actually see the detection happening, it was very unreliable or extremely slow when at the beginning of the string, I had to rely on temporary usage of the clipboard, etc.

Code: Select all

ClipboardBackup := ClipboardAll
Clipboard := 
SendInput, {Shift Down}{Home}{Shift Up}^c
; ClipWait can't do sub-second waiting
Sleep, 100
TextToLeft := Clipboard
If (TextToLeft){
	; If there is text to the left then the text cursor / caret is not at the very beginning so pressing the right arrow key will cancel the text selection
	SendInput, {Right 1}
} Else {
	; If there is not text to the left then the text cursor / caret is at the very beginning so pressing the left arrow key will cancel the text selection
	SendInput, {Left 1}
}

Clipboard := ClipboardBackup
2020 ∕ 11 ∕ 13 23꞉07꞉27.gif
2020 ∕ 11 ∕ 13 23꞉07꞉27.gif (34.74 KiB) Viewed 186 times
I toyed around with other ideas such as estimating the position by tracking inputs and/or using the width of the control and X co-ordinates of the caret but quickly realised how many different ways that would fail.

However, earlier this evening, I had a lightbulb / brainwave moment. What if I were to very quickly send an extremely rare character, get its position, and then delete it?

Slight tangent: Recently, I've really started to appreciate the value of Unicode characters (which I've written about at https mythofechelon.co.uk /blog/2020/3/6/how-to-work-around-windows-restricted-characters) Broken Link for safety and, the other day, I was configuring a Splunk alert and it required a message to be entered because it'd set its default text otherwise so I went looking for an "unprintable" (invisible) Unicode character and found just the thing: U+200E (Left-to-Right Mark (LRM))! (The RTLO character is an alternative but it can be flagged as malicious.)

So, it turns out that the combination of this idea and this character works perfectly!

Code: Select all

ControlGetFocus, FocusedControl
If (FocusedControl == "Edit1" Or FocusedControl == "Edit2"){
	SendInput, {U+200E}
	Sleep 50 ; Seems that SendInput isn't synchronous so need to wait a tiny bit before retrieving the new string
	ControlGetText, String, %FocusedControl%
	SendInput, {Backspace}
	StringLength := StrLen(String)
	CaretPosition := InStr(String, "‎") ; ← "‎" actually contains a U+200E unprintable / invisible Left-to-Right Mark (LRM) character
	TextToLeft := SubStr(String, 1, CaretPosition)
	TextToRight := SubStr(String, (CaretPosition - StringLength))
	
	ToolTip, String: %String%`nStringLength: %StringLength%`nCaretPosition: %CaretPosition%`nTextToLeft: %TextToLeft%`nTextToRight: %TextToRight%
}
2020 ∕ 11 ∕ 14 15꞉40꞉56.gif
2020 ∕ 11 ∕ 14 15꞉40꞉56.gif (31.14 KiB) Viewed 139 times
I just thought I'd post this here for the good of others, seeing as I've never found a solution anywhere near as good online before. :)

Return to “Tutorials”

Who is online

Users browsing this forum: No registered users and 8 guests