如何获取Windows各类软件的“插入/输入光标【caret】”的x、y坐标?

autohotkey v1 有A_caretX A_caretY,v2 有CaretGetPos(&X, &Y)

但是都只适用于少部分程序。
有没有现成的,能适用于更多/绝大部分程序的 方法呢?

就像微软输入法/搜狗输入法那样,几乎适配所有窗口?

PS Autoahk网站 新建标签页 (autoahk.com)打不开了?破产了嘛?谁知道?


找到一段代码,autohotkey V1版本的,谁知道怎么转V2版本么?
试了网上找的代码转换器,转出来的不能用。

$F1::
   if !GetCaretPos(x, y)
      MsgBox, Cant recognize caret position
   else {
      CoordMode, Mouse
      MouseMove, x, y
   }
   Return

GetCaretPos(ByRef x, ByRef y) {
   static OBJID_CARET := 0xFFFFFFF8
   CoordMode, Caret
   if (A_CaretX != "" && A_CaretY != "")
      x := A_CaretX, y := A_CaretY
   else {
      AccObject := AccObjectFromWindow(WinExist("A"), OBJID_CARET)
      Pos := AccLocation(AccObject)
      x := Pos.x, y := Pos.y
   }
   Return x && y
}

AccObjectFromWindow(hWnd, idObject = 0) {
   static IID_IDispatch   := "{00020400-0000-0000-C000-000000000046}"
        , IID_IAccessible := "{618736E0-3C3D-11CF-810C-00AA00389B71}"
        , OBJID_NATIVEOM  := 0xFFFFFFF0, VT_DISPATCH := 9, F_OWNVALUE := 1
        , h := DllCall("LoadLibrary", "Str", "oleacc", "Ptr")
        
   VarSetCapacity(IID, 16), idObject &= 0xFFFFFFFF, AccObject := 0
   DllCall("ole32\CLSIDFromString", "Str", idObject = OBJID_NATIVEOM ? IID_IDispatch : IID_IAccessible, "Ptr", &IID)
   if DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", idObject, "Ptr", &IID, "PtrP", pAcc) = 0
      AccObject := ComObject(VT_DISPATCH, pAcc, F_OWNVALUE)
   Return AccObject
}

AccLocation(Acc, ChildId := 0, ByRef Position := "") {
   static type := (VT_BYREF := 0x4000) | (VT_I4 := 3)
   try Acc.accLocation( ComObject(type, &x := 0), ComObject(type, &y := 0)
                      , ComObject(type, &w := 0), ComObject(type, &h := 0), ChildId )
   catch
      Return
   _x := NumGet(x, "int"), _y := NumGet(y, "int"), _w = NumGet(w, "int"), _h := NumGet(h, "int")
   Position := "x" . _x . " y" . _y . " w" . _w . " h" . _h
   Return {x: _x, y: _y, w: _w, h: _h}
}

我记得这个网站中文帮助要收费, 很久都没访问的.

查了一下资料(以下信息来自公开网络)

9月份还是正常的. 个人备案的国内网站.

image

成立了一个企业(个体工商户)

营口市西市区智能热键科技工作室

目前因经营异常被工商管理部门注销

不收费呀,我一直就在这个网站查帮助

我记得是免费放出的是旧版帮助, 最新版需要付费.

就自带的那个windows spy.ahk就能查看坐标啊
我发不了图
mouse position:
screen:321,321
Window:123,123

Window就是软件窗口里的具体坐标

用法如下,是我自用开机脚本里的点击微信的登录按钮
ControlClick, x142 y283, 微信 ahk_class WeChatLoginWndForPC

那个叫 鼠标光标 mouse cursor
我说的是 插入光标 caret

如图,这个一闪一闪的竖杠:
1

刚好有这样的需求

先下载 lib
Acc Lib

然后这样就行了
acc失败的情况返回的是空,所以需要最好用IsNumber判断下返回值

#Include <Acc>
CoordMode("Caret")

Sleep(2000)
GetCaretPos(&x,&y)
if IsNumber(x) && IsNumber(y)
    MsgBox(x "@" y)

GetCaretPos(&x, &y)
{
    if CaretGetPos(&x, &y)
        return
    else
    {
        static OBJID_CARET := 0xFFFFFFF8
        try
        {
            oacc := Acc.ObjectFromWindow(WinExist("a"), OBJID_CARET)
            pos := oacc.Location
            x := pos.x
            y := pos.y
        }
        catch
            x := y := ""
    }
}

wow,autoahk又活了,前些天一直不能访问。。。

大佬可以用楼上的方法更新下输入法指示器了 :star_struck:

输入法指示器不是我写的,你艾特下他吧。

啊这,记错了好尴尬:rofl:,忘了他那个不是AHK写的

ACC ,hook 之外的新方法,UIA

  • ahk v1 UIA
GetCaret(ByRef X:="", ByRef Y:="", ByRef W:="", ByRef H:="") {

    ; UIA caret
    static IUIA := ComObjCreate("{ff48dba4-60ef-4201-aa87-54103eef594e}", "{30cbe57d-d9d0-452a-ab13-7ac5ac4825ee}")
    ; GetFocusedElement
    DllCall(NumGet(NumGet(IUIA+0)+8*A_PtrSize), "ptr", IUIA, "ptr*", FocusedEl:=0)
    ; GetCurrentPattern. TextPatternElement2 = 10024
    DllCall(NumGet(NumGet(FocusedEl+0)+16*A_PtrSize), "ptr", FocusedEl, "int", 10024, "ptr*", patternObject:=0), ObjRelease(FocusedEl)
    if patternObject {
        ; GetCaretRange
        DllCall(NumGet(NumGet(patternObject+0)+10*A_PtrSize), "ptr", patternObject, "int*", IsActive:=1, "ptr*", caretRange:=0), ObjRelease(patternObject)
        ; GetBoundingRectangles
        DllCall(NumGet(NumGet(caretRange+0)+10*A_PtrSize), "ptr", caretRange, "ptr*", boundingRects:=0), ObjRelease(caretRange)
        ; VT_ARRAY = 0x20000 | VT_R8 = 5 (64-bit floating-point number)
        Rect := ComObject(0x2005, boundingRects)
        if (Rect.MaxIndex() = 3) {
            X:=Round(Rect[0]), Y:=Round(Rect[1]), W:=Round(Rect[2]), H:=Round(Rect[3])
            return
        }
    }

    ; Acc caret
    static _ := DllCall("LoadLibrary", "Str","oleacc", "Ptr")
    idObject := 0xFFFFFFF8 ; OBJID_CARET
    if DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", WinExist("A"), "UInt", idObject&=0xFFFFFFFF, "Ptr", -VarSetCapacity(IID,16)+NumPut(idObject==0xFFFFFFF0?0x46000000000000C0:0x719B3800AA000C81,NumPut(idObject==0xFFFFFFF0?0x0000000000020400:0x11CF3C3D618736E0,IID,"Int64"),"Int64"), "Ptr*", pacc:=0)=0 {
        oAcc := ComObjEnwrap(9,pacc,1)
        oAcc.accLocation(ComObj(0x4003,&_x:=0), ComObj(0x4003,&_y:=0), ComObj(0x4003,&_w:=0), ComObj(0x4003,&_h:=0), 0)
        X:=NumGet(_x,0,"int"), Y:=NumGet(_y,0,"int"), W:=NumGet(_w,0,"int"), H:=NumGet(_h,0,"int")
        if (X | Y) != 0
            return
    }

    ; default caret
    CoordMode Caret, Screen
    X := A_CaretX
    Y := A_CaretY
    W := 4
    H := 20
}
  • ahk v2 UIA2
GetCaret(&X?, &Y?, &W?, &H?) {
    ; UIA2 caret
    static IUIA := ComObject("{e22ad333-b25f-460c-83d0-0581107395c9}", "{34723aff-0c9d-49d0-9896-7ab52df8cd8a}")
    try {
        ComCall(8, IUIA, "ptr*", &FocusedEl:=0) ; GetFocusedElement
        ComCall(16, FocusedEl, "int", 10024, "ptr*", &patternObject:=0), ObjRelease(FocusedEl) ; GetCurrentPattern. TextPatternElement2 = 10024
        if patternObject {
            ComCall(10, patternObject, "int*", &IsActive:=1, "ptr*", &caretRange:=0), ObjRelease(patternObject) ; GetCaretRange
            ComCall(10, caretRange, "ptr*", &boundingRects:=0), ObjRelease(caretRange) ; GetBoundingRectangles
            if (Rect := ComValue(0x2005, boundingRects)).MaxIndex() = 3 { ; VT_ARRAY | VT_R8
                X:=Round(Rect[0]), Y:=Round(Rect[1]), W:=Round(Rect[2]), H:=Round(Rect[3])
                return
            }
        }
    }

    ; Acc caret
    static _ := DllCall("LoadLibrary", "Str","oleacc", "Ptr")
    try {
        idObject := 0xFFFFFFF8 ; OBJID_CARET
        if DllCall("oleacc\AccessibleObjectFromWindow", "ptr", WinExist("A"), "uint",idObject &= 0xFFFFFFFF
            , "ptr",-16 + NumPut("int64", idObject == 0xFFFFFFF0 ? 0x46000000000000C0 : 0x719B3800AA000C81, NumPut("int64", idObject == 0xFFFFFFF0 ? 0x0000000000020400 : 0x11CF3C3D618736E0, IID := Buffer(16)))
            , "ptr*", oAcc := ComValue(9,0)) = 0 {
            x:=Buffer(4), y:=Buffer(4), w:=Buffer(4), h:=Buffer(4)
            oAcc.accLocation(ComValue(0x4003, x.ptr, 1), ComValue(0x4003, y.ptr, 1), ComValue(0x4003, w.ptr, 1), ComValue(0x4003, h.ptr, 1), 0)
            X:=NumGet(x,0,"int"), Y:=NumGet(y,0,"int"), W:=NumGet(w,0,"int"), H:=NumGet(h,0,"int")
            if (X | Y) != 0
                return
        }
    }

    ; Default caret
    savedCaret := A_CoordModeCaret, W := 4, H := 20
    CoordMode "Caret", "Screen"
    CaretGetPos(&X, &Y)
    CoordMode "Caret", savedCaret
}
1 个赞

都有缺点,唯一没有缺点的方法是让输入法支持一个坐标接口

获取文本插入点光标坐标——增强版 - AutoAHK

这位大佬前几天还更了个增强版

1 个赞