January 8th, 2026
like2 reactions

Using Active Accessibility to find out where the Windows caret is

Last time, we learned how to query the global caret position, but we found that it works only for programs that use the system caret. Fancy programs think that the system caret is old and stodgy and prefer to draw their own caret. How can we learn about those custom carets?

We can use the classic Active Accessibility interface IAccessible and ask the focus window for its caret. Programs that draw their own custom caret are expected to respond to this by telling you where their custom caret is.

GUITHREADINFO info = { sizeof(GUITHREADINFO) };
if (GetGUIThreadInfo(0, &info))
{
    if (info.flags & GUI_CARETBLINKING)
    {
        MapWindowPoints(info.hwndCaret, nullptr, (POINT*)&info.rcCaret, 2);
        SetCursorPos(info.rcCaret.right - 1, info.rcCaret.bottom - 1);
        return;
    }
    if (info.hwndFocus != nullptr) {                                         
        Microsoft::WRL::ComPtr<IAccessible> acc;                             
        if (SUCCEEDED(AccessibleObjectFromWindow(info.hwndFocus, OBJID_CARET,
                              IID_PPV_ARGS(&acc))) && acc) {                 
            long x, y, cx, cy;                                               
            VARIANT vt{};                                                    
            vt.vt = VT_I4;                                                   
            vt.lVal = CHILDID_SELF;                                          
            if (acc->accLocation(&x, &y, &cx, &cy, vt) == S_OK) {            
                SetCursorPos(x + cx - 1, y + cy - 1);                        
                return;                                                      
            }                                                                
        }                                                                    
    }                                                                        
}

This detects the caret in most programs that use a custom caret. I tried Visual Studio, Chromium-based programs, and Microsoft Word, and they all worked. (However, Terminal and Calculator in Worksheet mode didn’t work. They fail to report a caret at all. Sad.)

In the original problem formulation, the goal was to move the cursor to the keyboard focus. The keyboard focus might be represented by a caret, but it might be a selected item on the desktop or some other non-textual focus. We’ll look at that next time.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

1 comment

Sort by :
  • LB

    By Terminal, do you mean Microsoft’s Windows Terminal app? I just tested and the Windows 10 emoji picker knows where the caret is, so I guess they expose it to IME but not to accessibility?