How to get Caret string position from Edit Controls? Topic is solved

Get help with using AutoHotkey and its commands and hotkeys
User
Posts: 407
Joined: 26 Jun 2017, 08:12

How to get Caret string position from Edit Controls?

25 Oct 2017, 09:37

[Solution]: I wrote C_Caret(Function) that can easily get Caret info relative to the specified control's client area!

Is it possible to get Caret string position from Edit Controls?

What I already tried:

Code: Select all

gui, add, edit, w300 h200 gGetCaret +HwndControlId, 
gui, add, Text, w300 vCaretInfo, Caret Info

gosub, GetCaret

gui, show
return

GetCaret:	;________ get carete position _____
~LButton::	;"~" keeps the button original function
~Up::
~Right::
~Left::
~Down::

sleep, 50	;necessary in order to get the correct caret info

ControlGet, CaretLine, CurrentLine, , , % "ahk_id" ControlId
ControlGet, CaretCol, CurrentCol, , , % "ahk_id" ControlId

guicontrol, , CaretInfo, % "CaretLine: " . CaretLine . " \ CaretCol: " . CaretCol . " \ CaretPos: ? "

return

guiclose:	;____________ gui close __________
exitapp
Carte Info.png
Carte Info.png (6.18 KiB) Viewed 7041 times
Last edited by User on 01 Nov 2017, 11:39, edited 1 time in total.
User avatar
LinearSpoon
Posts: 156
Joined: 29 Sep 2013, 22:55

Re: How to get Caret string position from Edit Controls?

25 Oct 2017, 11:45

One solution with the EM_GETSEL message:

Code: Select all

gui, add, edit, w300 h200 gGetCaret +HwndControlId, 
gui, add, Text, w300 vCaretInfo, Caret Info

gosub, GetCaret

gui, show
return

GetCaret:	;________ get carete position _____
~*LButton::	;"~" keeps the button original function
~*Up::
~*Right::
~*Left::
~*Down::

sleep, 50	;necessary in order to get the correct caret info

ControlGet, CaretLine, CurrentLine, , , % "ahk_id" ControlId
ControlGet, CaretCol, CurrentCol, , , % "ahk_id" ControlId
selection := getEditSelection(ControlId)

guicontrol, , CaretInfo, % "CaretLine: " . CaretLine . " \ CaretCol: " . CaretCol . " \ CaretPos: " selection.start ", " selection.end

return

guiclose:	;____________ gui close __________
exitapp

getEditSelection(hwnd)
{
  ; EM_GETSEL
  VarSetCapacity(buf, 8)
  SendMessage, 0xB0, &buf, &buf+4,, ahk_id %hwnd%
  return { start: NumGet(buf, 0, "uint"), end: NumGet(buf, 4, "uint") }
}
User
Posts: 407
Joined: 26 Jun 2017, 08:12

Re: How to get Caret string position from Edit Controls?

25 Oct 2017, 13:08

LinearSpoon wrote: .
Well, I was expecting for a simpler solution, but anyway, if using a function is the only way to go, so be it!

Thanks!
User
Posts: 407
Joined: 26 Jun 2017, 08:12

Re: How to get Caret string position from Edit Controls?

27 Oct 2017, 00:13

LinearSpoon wrote:.
Hi @LinearSpoon,

Just to let you know that I just wrote right now "CaretPos(Function)" that returns the exact Caret string position!

if you are interested to test it, feel free to do it and in case you find any bug, please report here:

Testing in Notepad
Get Caret & Selected String Start-End Position.gif
Get Caret & Selected String Start-End Position.gif (612.42 KiB) Viewed 6974 times

Code: Select all

	;https://autohotkey.com/boards/viewtopic.php?p=27979#p27979
	;https://autohotkey.com/boards/viewtopic.php?f=5&t=38892


loop, 15
Text .= "AAAAAAAAAA`n"

sleep, 125

;"+Hwnd" store the control id number in "ControlId" variable
gui, add, edit, w350 h300 gGetCaretSelString +HwndControlId, % text

gui, show
gosub, GetCaretSelString
return

;_______________ Get Caret and Selected String Info __________________

~LButton Up::	;"~" keeps the button original function

MouseGetPos, , , WinId, ControlId, 2	;"2" Stores the control's HWND in "ControlId" variable rather than the control's ClassNN.

~Up::
~Right::
~Left::
~Down::

GetCaretSelString:

sleep, 50	;necessary in order to get the correct info

ControlGet, SelStartPosL, CurrentLine, , , % "ahk_id" ControlId		;get "line" from the selected string start pos (get from caret pos if no string is selected)
ControlGet, SelStartPosC, CurrentCol, , , % "ahk_id" ControlId		;get "col" from the selected string start pos (get from caret pos if no string is selected)

;Get start and End Pos of the selected string - Get Caret pos if no string is selected
;https://autohotkey.com/boards/viewtopic.php?p=27979#p27979
;EM_GETSEL = 0x00B0 -> msdn.microsoft.com/en-us/library/bb761598(v=vs.85).aspx
DllCall("User32.dll\SendMessage", "Ptr", ControlId, "UInt", 0x00B0, "UIntP", Start, "UIntP", End, "Ptr")
start++, end++	;force "1" instead "0" to be recognised as the beginning of the string!

tooltip, % ""
. "Caret Pos: " . CaretPos(ControlId) . "`n"
. "Selected String (Start/End Pos): " . Start . "/" . End . "`n"
. "Selected String (Start Pos Line/Col): " . SelStartPosL . "\" . SelStartPosC . "`n"
. "WinId: " . WinId . " \ ControlId: " . ControlId .  "`n"

return

guiclose:	;____________ gui close __________
exitapp


CaretPos(ControlId) ;___________ CaretPos v1.0 (Function) ______________
{
;Get start and End Pos of the selected string - Get Caret pos if no string is selected
;https://autohotkey.com/boards/viewtopic.php?p=27979#p27979
;EM_GETSEL = 0x00B0 -> msdn.microsoft.com/en-us/library/bb761598(v=vs.85).aspx
DllCall("User32.dll\SendMessage", "Ptr", ControlId, "UInt", 0x00B0, "UIntP", Start, "UIntP", End, "Ptr")

;"0xB1", EM_SETSEL
;Remove any string selection and keep the "caret" position unchanged!
SendMessage, 0xB1, -1, 0, , % "ahk_id" ControlId

;Get "Caret" pos because no string is selected!
DllCall("User32.dll\SendMessage", "Ptr", ControlId, "UInt", 0x00B0, "UIntP", CaretPos, "UIntP", CaretPos, "Ptr")


if (CaretPos = End)
SendMessage, 0xB1, % Start, % End, , % "ahk_id" ControlId	;select from left to righ ("caret" at the End of the selection)
else
SendMessage, 0xB1, % End, % Start, , % "ahk_id" ControlId	;select from right to left ("caret" at the Start of the selection)
;"Start" is always smaller or equal to "End"

CaretPos++	;force "1" instead "0" to be recognised as the beginning of the string!

return, CaretPos
}
User
Posts: 407
Joined: 26 Jun 2017, 08:12

Re: How to get Caret string position from Edit Controls?  Topic is solved

31 Oct 2017, 23:16

C_Caret(Function), get Caret info relative to the specified control's client area!

This function is better than "CaretPos(Function)" above because it does not use the Deselect\Select method!

First, the function must be called specifying a Control hwnd in order to get the caret S,L,X,Y positions!
Example, C_Caret(ControlId)

Then specify one of the letters to get their values!
Get Caret String Position, C_Caret("S")
Get Caret Line Position, C_Caret("L")
Get Caret X Position, C_Caret("X")
Get Caret Y Position, C_Caret("Y")

Code: Select all

	;https://autohotkey.com/boards/viewtopic.php?p=179374#p179374
	;https://autohotkey.com/boards/viewtopic.php?p=178225#p178225


CoordMode, Caret, screen

text := "
(
Lorem ipsum dolor sit amet
Consectetuer ligula Aliquam Curabitur Nullam
Rutrum eu est congue dui
Interdum Phasellus sed Quisque Donec
Et semper adipiscing id Sed
Non ut Quisque Pellentesque lorem
Est at urna justo sem
Proin consequat gravida nibh adipiscing
)"

gui, add, edit, w260 h150, % "(With border) `n" text
gui, add, edit, x+5 w260 h150 -E0x200, % "(Without border) `n" text	;"-E0x200" remove border
gui, add, text, xm, - Text - 
gui, add, text, x+5 +border, - Text - 
gui, add, button, x+5, Button
gui, add, button, x+5 +Border, Button

gui, show
return

~Lbutton up::	;"~" keeps the button original function

MouseGetPos, , , WinId, ControlId, 2	;"2" Stores the control's HWND in "ControlId" variable rather than the control's ClassNN.

~Up::
~Right::
~Left::
~Down::

sleep, 50

WinGetPos, CtrlX, CtrlY, , , % "ahk_id" ControlId	;"WinGetPos" can be used to get controls xy pos relative to screen upper-left corner

VarSetCapacity(WINDOWINFO, 60, 0)
DllCall("GetWindowInfo", Ptr, ControlId, Ptr, &WINDOWINFO)
CtrlClientX := NumGet(WINDOWINFO, 20, "Int")
CtrlClientY := NumGet(WINDOWINFO, 24, "Int")

;Get start and End Pos of the selected string - Get Caret pos if no string is selected
;https://autohotkey.com/boards/viewtopic.php?p=27979#p27979
;EM_GETSEL = 0x00B0 -> msdn.microsoft.com/en-us/library/bb761598(v=vs.85).aspx
DllCall("User32.dll\SendMessage", "Ptr", ControlId, "UInt", 0x00B0, "UIntP", Start, "UIntP", End, "Ptr")
start++, end++	;force "1" instead "0" to be recognised as the beginning of the string!

tooltip % ""
. "XY pos relative to screen upper-left corner: `n"
. "Control XY Pos: " CtrlX "," CtrlY "`n"
. "Control Client Area XY pos: " CtrlClientX "," CtrlClientY "`n"
. "A_CaretX \ A_CaretY: " A_CaretX "," A_Carety "`n"
. "`n"
. "Caret String Pos: " . C_Caret(ControlId) . C_Caret("S") . " \ Caret Line: " . C_Caret("L") .  "`n"
. "Selected String (Start\End): " . Start "\" End "`n"
. "Caret XY pos from control Client Area: " . C_Caret("x") "," C_Caret("y") "`n"
. "`n"
. "WinId: " . WinId . " \ ControlId: " . ControlId .  "`n"

return

guiclose:	;____________ gui close ___________
exitapp


C_Caret(ControlId)	;_________ C_Caret(Function) - v1.0 __________ 
{
;This function returns the Caret info relative to the specified Control's client area!
;if "ControlId = a Control Hwnd Id" the function will get the Caret S,L,X,Y positions!
;if "ControlId = S" the function returns the Caret String Position
;if "ControlId = L" the function returns the Caret Line Position
;if "ControlId = X" the function returns the Caret x Position
;if "ControlId = Y" the function returns the Caret Y Position

Static S,L,X,Y		;remember values between function calls

if (ControlId = "S")
return, S
else if (ControlId = "L")
return, L
else if (ControlId = "X")
return, X
else if (ControlId = "Y")
return, Y

T_CoordModeCaret := A_CoordModeCaret	;necessary to restore thread default option before function return
CoordMode, Caret, screen
sleep, 1				;prevents A_CaretX\A_Carety from returning incorrect values

VarSetCapacity(WINDOWINFO, 60, 0)
DllCall("GetWindowInfo", Ptr, ControlId, Ptr, &WINDOWINFO)

X := A_CaretX - NumGet(WINDOWINFO, 20, "Int")	;"20" returns the control client area x pos relative to screen upper-left corner
Y := A_Carety - NumGet(WINDOWINFO, 24, "Int")	;"24" returns the control client area y pos relative to screen upper-left corner

;EM_CHARFROMPOS = 0x00D7 -> msdn.microsoft.com/en-us/library/bb761566(v=vs.85).aspx
Char := DllCall("User32.dll\SendMessage", "Ptr", ControlId, "UInt", 0x00D7, "Ptr", 0, "UInt", (Y << 16) | X, "Ptr")

S := (Char & 0xFFFF) + 1	;"+1" force 1 instead 0 to be recognised as first character
L := (Char >> 16) + 1

CoordMode, Caret, % T_CoordModeCaret	;restore thread default option before function return
sleep, 1				;prevents A_CaretX\A_Carety from returning incorrect values
}
User avatar
hasantr
Posts: 780
Joined: 05 Apr 2016, 14:18
Location: İstanbul

Re: How to get Caret string position from Edit Controls?

23 Dec 2020, 20:11

User wrote:
31 Oct 2017, 23:16
C_Caret(Function), get Caret info relative to the specified control's client area!

This function is better than "CaretPos(Function)" above because it does not use the Deselect\Select method!

First, the function must be called specifying a Control hwnd in order to get the caret S,L,X,Y positions!
Example, C_Caret(ControlId)

Then specify one of the letters to get their values!
Get Caret String Position, C_Caret("S")
Get Caret Line Position, C_Caret("L")
Get Caret X Position, C_Caret("X")
Get Caret Y Position, C_Caret("Y")

Code: Select all

	;https://autohotkey.com/boards/viewtopic.php?p=179374#p179374
	;https://autohotkey.com/boards/viewtopic.php?p=178225#p178225


CoordMode, Caret, screen

text := "
(
Lorem ipsum dolor sit amet
Consectetuer ligula Aliquam Curabitur Nullam
Rutrum eu est congue dui
Interdum Phasellus sed Quisque Donec
Et semper adipiscing id Sed
Non ut Quisque Pellentesque lorem
Est at urna justo sem
Proin consequat gravida nibh adipiscing
)"

gui, add, edit, w260 h150, % "(With border) `n" text
gui, add, edit, x+5 w260 h150 -E0x200, % "(Without border) `n" text	;"-E0x200" remove border
gui, add, text, xm, - Text - 
gui, add, text, x+5 +border, - Text - 
gui, add, button, x+5, Button
gui, add, button, x+5 +Border, Button

gui, show
return

~Lbutton up::	;"~" keeps the button original function

MouseGetPos, , , WinId, ControlId, 2	;"2" Stores the control's HWND in "ControlId" variable rather than the control's ClassNN.

~Up::
~Right::
~Left::
~Down::

sleep, 50

WinGetPos, CtrlX, CtrlY, , , % "ahk_id" ControlId	;"WinGetPos" can be used to get controls xy pos relative to screen upper-left corner

VarSetCapacity(WINDOWINFO, 60, 0)
DllCall("GetWindowInfo", Ptr, ControlId, Ptr, &WINDOWINFO)
CtrlClientX := NumGet(WINDOWINFO, 20, "Int")
CtrlClientY := NumGet(WINDOWINFO, 24, "Int")

;Get start and End Pos of the selected string - Get Caret pos if no string is selected
;https://autohotkey.com/boards/viewtopic.php?p=27979#p27979
;EM_GETSEL = 0x00B0 -> msdn.microsoft.com/en-us/library/bb761598(v=vs.85).aspx
DllCall("User32.dll\SendMessage", "Ptr", ControlId, "UInt", 0x00B0, "UIntP", Start, "UIntP", End, "Ptr")
start++, end++	;force "1" instead "0" to be recognised as the beginning of the string!

tooltip % ""
. "XY pos relative to screen upper-left corner: `n"
. "Control XY Pos: " CtrlX "," CtrlY "`n"
. "Control Client Area XY pos: " CtrlClientX "," CtrlClientY "`n"
. "A_CaretX \ A_CaretY: " A_CaretX "," A_Carety "`n"
. "`n"
. "Caret String Pos: " . C_Caret(ControlId) . C_Caret("S") . " \ Caret Line: " . C_Caret("L") .  "`n"
. "Selected String (Start\End): " . Start "\" End "`n"
. "Caret XY pos from control Client Area: " . C_Caret("x") "," C_Caret("y") "`n"
. "`n"
. "WinId: " . WinId . " \ ControlId: " . ControlId .  "`n"

return

guiclose:	;____________ gui close ___________
exitapp


C_Caret(ControlId)	;_________ C_Caret(Function) - v1.0 __________ 
{
;This function returns the Caret info relative to the specified Control's client area!
;if "ControlId = a Control Hwnd Id" the function will get the Caret S,L,X,Y positions!
;if "ControlId = S" the function returns the Caret String Position
;if "ControlId = L" the function returns the Caret Line Position
;if "ControlId = X" the function returns the Caret x Position
;if "ControlId = Y" the function returns the Caret Y Position

Static S,L,X,Y		;remember values between function calls

if (ControlId = "S")
return, S
else if (ControlId = "L")
return, L
else if (ControlId = "X")
return, X
else if (ControlId = "Y")
return, Y

T_CoordModeCaret := A_CoordModeCaret	;necessary to restore thread default option before function return
CoordMode, Caret, screen
sleep, 1				;prevents A_CaretX\A_Carety from returning incorrect values

VarSetCapacity(WINDOWINFO, 60, 0)
DllCall("GetWindowInfo", Ptr, ControlId, Ptr, &WINDOWINFO)

X := A_CaretX - NumGet(WINDOWINFO, 20, "Int")	;"20" returns the control client area x pos relative to screen upper-left corner
Y := A_Carety - NumGet(WINDOWINFO, 24, "Int")	;"24" returns the control client area y pos relative to screen upper-left corner

;EM_CHARFROMPOS = 0x00D7 -> msdn.microsoft.com/en-us/library/bb761566(v=vs.85).aspx
Char := DllCall("User32.dll\SendMessage", "Ptr", ControlId, "UInt", 0x00D7, "Ptr", 0, "UInt", (Y << 16) | X, "Ptr")

S := (Char & 0xFFFF) + 1	;"+1" force 1 instead 0 to be recognised as first character
L := (Char >> 16) + 1

CoordMode, Caret, % T_CoordModeCaret	;restore thread default option before function return
sleep, 1				;prevents A_CaretX\A_Carety from returning incorrect values
}
This function is great.

Return to “Ask For Help”

Who is online

Users browsing this forum: adrian88888888, ameyrick, Arsonistic, bsap, JoeWinograd, mikeyww, Spawnova, TAC109, vmech, XMCQCX, Xtra and 40 guests