{"id":111973,"date":"2026-01-08T07:00:00","date_gmt":"2026-01-08T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=111973"},"modified":"2026-01-08T08:44:09","modified_gmt":"2026-01-08T16:44:09","slug":"20260108-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20260108-00\/?p=111973","title":{"rendered":"Using Active Accessibility to find out where the Windows caret is"},"content":{"rendered":"<p>Last time, <a title=\"How can I find out where the Windows caret is?\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20260107-00\/?p=111971\"> we learned how to query the global caret position<\/a>, 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?<\/p>\n<p>We can use the classic Active Accessibility interface <code>IAccessible<\/code> 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.<\/p>\n<pre>GUITHREADINFO info = { sizeof(GUITHREADINFO) };\r\nif (GetGUIThreadInfo(0, &amp;info))\r\n{\r\n    if (info.flags &amp; GUI_CARETBLINKING)\r\n    {\r\n        MapWindowPoints(info.hwndCaret, nullptr, (POINT*)&amp;info.rcCaret, 2);\r\n        SetCursorPos(info.rcCaret.right - 1, info.rcCaret.bottom - 1);\r\n        return;\r\n    }\r\n    <span style=\"border: solid 1px currentcolor; border-bottom: none;\">if (info.hwndFocus != nullptr) {                                         <\/span>\r\n    <span style=\"border: 1px currentcolor; border-style: none solid;\">    Microsoft::WRL::ComPtr&lt;IAccessible&gt; acc;                             <\/span>\r\n    <span style=\"border: 1px currentcolor; border-style: none solid;\">    if (SUCCEEDED(AccessibleObjectFromWindow(info.hwndFocus, OBJID_CARET,<\/span>\r\n    <span style=\"border: 1px currentcolor; border-style: none solid;\">                          IID_PPV_ARGS(&amp;acc))) &amp;&amp; acc) {                 <\/span>\r\n    <span style=\"border: 1px currentcolor; border-style: none solid;\">        long x, y, cx, cy;                                               <\/span>\r\n    <span style=\"border: 1px currentcolor; border-style: none solid;\">        VARIANT vt{};                                                    <\/span>\r\n    <span style=\"border: 1px currentcolor; border-style: none solid;\">        vt.vt = VT_I4;                                                   <\/span>\r\n    <span style=\"border: 1px currentcolor; border-style: none solid;\">        vt.lVal = CHILDID_SELF;                                          <\/span>\r\n    <span style=\"border: 1px currentcolor; border-style: none solid;\">        if (acc-&gt;accLocation(&amp;x, &amp;y, &amp;cx, &amp;cy, vt) == S_OK) {            <\/span>\r\n    <span style=\"border: 1px currentcolor; border-style: none solid;\">            SetCursorPos(x + cx - 1, y + cy - 1);                        <\/span>\r\n    <span style=\"border: 1px currentcolor; border-style: none solid;\">            return;                                                      <\/span>\r\n    <span style=\"border: 1px currentcolor; border-style: none solid;\">        }                                                                <\/span>\r\n    <span style=\"border: 1px currentcolor; border-style: none solid;\">    }                                                                    <\/span>\r\n    <span style=\"border: solid 1px currentcolor; border-top: none;\">}                                                                        <\/span>\r\n}\r\n<\/pre>\n<p>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&#8217;t work. They fail to report a caret at all. Sad.)<\/p>\n<p>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&#8217;ll look at that next time.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It&#8217;s old and rather simple, but we like simple.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-111973","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>It&#8217;s old and rather simple, but we like simple.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111973","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=111973"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111973\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=111973"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=111973"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=111973"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}