question

AndrewNasonov-0450 avatar image
0 Votes"
AndrewNasonov-0450 asked AndrewNasonov-0450 commented

How to get caret position in ANY application from C#?

Like Clipboard in Windows 10/11 (Win + V) - it always know current caret position on the page in Google Chrome or MS Edge, also in other applications - WPF, WinForms, UWP, etc.

I'm trying to get caret position in windows. Even if it's not native.

Tried to use Win32 API GetCaretPos function (https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getcaretpos), and it's worked, but only for WPF/WinForms processes. In case if application has own caret implementation (like Google Chrome browser) that function doesn't work.

var hFore = GetForegroundWindow();
var idAttach = GetWindowThreadProcessId(hFore, out uint id);
var curThreadId = GetCurrentThreadId();

// To attach to current thread
var sa = AttachThreadInput(idAttach, curThreadId, true);

var caretPos = WindowsKeyboard.GetCaretPos(out POINT caretPoint);

ClientToScreen(hFore, ref caretPoint);

// To dettach from current thread
var sd = AttachThreadInput(idAttach, curThreadId, false);

var data = string.Format("X={0}, Y={1}", caretPoint.X, caretPoint.Y);

But caretPoint correct only for WPF/Win32/WinForms apps. Also, I noticed that solution https://www.codeproject.com/Articles/34520/Getting-Caret-Position-Inside-Any-Application doesn't work for some Windows Desktop apps like Google Chrome or VS Code, Slack, etc.

I expect to get cursor position to determine where to show popup window like it made by Microsoft with Clipboard History (Win + V) on Windows 10 or Windows 11.

dotnet-csharpwindows-api
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

Castorix31 avatar image
1 Vote"
Castorix31 answered AndrewNasonov-0450 commented

I did a quick test with MS Edge (Search TextBox on this page) on Windows 10 21H1 and it worked with
GetForegroundWindow + GetGUIThreadInfo to get hwndFocus, then AccessibleObjectFromWindow with OBJID_CARET, then IAccessible.accLocation




· 5
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thanks, but when i tried to call IAccessible.accLocation it throw exception Values does not fall within the expected range. It throws for Google Chrome, VS Code windows, etc. But for others it works as expected.

0 Votes 0 ·

Thanks, everything working OK. I forgot about [in] VARIANT varChild in accLocation function. It should be set to zero - it's CHILDID_SELF = 0

0 Votes 0 ·

Can you provide the full code that you used to do that in C#?
I'm a bit confused on how I should call AccessibleObjectFromWindow with OBJID_CARET and then IAccessible.accLocation

Thank you!

0 Votes 0 ·
 var guid = typeof(IAccessible).GUID;
 object accessibleObject = null;
 var retVal = WinApiProvider.AccessibleObjectFromWindow(hwnd, WinApiProvider.OBJID_CARET, ref guid, ref accessibleObject);
 var accessible = accessibleObject as IAccessible;
 accessible.accLocation(out int left, out int top, out int width, out int height, WinApiProvider.CHILDID_SELF);

@AndreaNagar-7624

0 Votes 0 ·

You need to add COM reference UIAutomationClient

0 Votes 0 ·