获取文本插入点 光标坐标 的解决方案,测试有效

动作开发 · 1013 次浏览
涛涛涛 创建于 2天15小时前

现查到两种方案可以获取 文本焦点 光标坐标
1.aardio作者写的一个库函数,此库可以 获取光标坐标 和 光标前后的文本 光标选择的文本等

2.AutoHotkey中文社区中的大神 Tebayaki  写的一个函数获取光标坐标 ( 推荐使用封装调用起来简单)

 方案一
winex.caret 库模块帮助文档     
aardio作者写的一个库函数  如果有需要可以去看一下
https://www.aardio.com/zh-cn/doc/?&q=aardio
https://www.aardio.com/zh-cn/doc/?&q=winex.caret
获取输入光标的屏幕位置。
winex.caret.get(hwnd) 
在 @hwnd 指定句柄的窗口获取输入光标位置。
不指定参数则获取前台窗口输入光标。 

例子:获取坐标后鼠标移过去,提示位置

使用了网络请求后台封装调用一下其函数库(生成的程序也很小2M)
http://127.0.0.1:10962         (测试时,wps表格和wps文档时可能无效,在微软表格和文档中获取正常)
1.发送请求获取输入光标的屏幕位置
响应数据为光标的屏幕位置:{"bottom":332,"hwnd":1312204,"left":1037,"right":1038,"top":312}   或  无焦点:{"aa":"wu"}
2.也可以通过剪贴板获取数据
{"bottom":332,"hwnd":1312204,"left":1037,"right":1038,"top":312}


方案二
AutoHotkey中文社区
获取文本插入点光标坐标——增强版
https://www.autoahk.com/archives/44158
v1版、v2版、C++源码版    有需要的,有能力的可以去看看编码调用

例子:获取坐标后鼠标移过去,提示位置(生成的程序也小1.2M)
通过热键有时也称为快捷键F13调用其函数GetCaretPosEx()获取文本插入点光标坐标后写入剪贴板
1.运行AutoHotkey热键F13,获取文本插入点光标坐标后写入剪贴板
数据格式:538|700|1|20
2.读取剪贴板

1.如果会aardio的可以使用下面的代码去生成exe程序调用
命令行调用即:cmd命令 程序.exe 参数(11\22\其他)

import win.ui;
import win.ui.atom;
import win.clip;
import winex.caret;
import winex.editor;
import JSON;
 
/*DSG{{*/
var winform = win.form(text="aardio form";right=400;bottom=200)
winform.add()
/*}}*/
 
var atom,hwnd/*冲突窗口的句柄,该函数会自动激活此窗口*/ = winform.atom("建议使用[工具->GUID]生成器生成");
if(!atom){
/*为窗口设置原子值可以避免一个程序重复运行多个实例*/
win.quitMessage(); return;
}
 
var aa = _CMDLINE;//命令行参数 即:cmd命令 程序.exe 参数(11\22\其他)
var bb;
 
if( aa="11" ){ 
//光标坐标位置
var caretRect = winex.caret.get();
bb=JSON.stringify(caretRect);
//写入剪贴板
win.clip.write(bb,true);
}
elseif(aa="22"){ 
//全中的文本
bb= winex.editor.caretText();
win.clip.write(bb,true);
}else{
//光标处文本框的全部文本
bb= winex.editor.getText();
win.clip.write(bb,true);
}



2.如果有安装AutoHotkey v2版的,可以使用如下代码在运行脚本的模块运行代码后,读取剪贴板数据就可以取到光标的位置坐标数据了

#Requires AutoHotkey v2.0

A_Clipboard := ""
if hwnd := GetCaretPosEx(&x, &y, &w, &h){
    a := x "|" y "|" w "|" h
    A_Clipboard := a
} else{
    A_Clipboard := "无焦点"
}

GetCaretPosEx(&x?, &y?, &w?, &h?) {
    x := h := w := h := 0
    static iUIAutomation := 0, hOleacc := 0, IID_IAccessible, guiThreadInfo, _ := init()
    if !iUIAutomation || ComCall(8, iUIAutomation, "ptr*", eleFocus := ComValue(13, 0), "int") || !eleFocus.Ptr
        goto useAccLocation
    if !ComCall(16, eleFocus, "int", 10002, "ptr*", valuePattern := ComValue(13, 0), "int") && valuePattern.Ptr
        if !ComCall(5, valuePattern, "int*", &isReadOnly := 0) && isReadOnly
            return 0
    useAccLocation:
    ; use IAccessible::accLocation
    hwndFocus := DllCall("GetGUIThreadInfo", "uint", DllCall("GetWindowThreadProcessId", "ptr", WinExist("A"), "ptr", 0, "uint"), "ptr", guiThreadInfo) && NumGet(guiThreadInfo, A_PtrSize == 8 ? 16 : 12, "ptr") || WinExist()
    if hOleacc && !DllCall("Oleacc\AccessibleObjectFromWindow", "ptr", hwndFocus, "uint", 0xFFFFFFF8, "ptr", IID_IAccessible, "ptr*", accCaret := ComValue(13, 0), "int") && accCaret.Ptr {
        NumPut("ushort", 3, varChild := Buffer(24, 0))
        if !ComCall(22, accCaret, "int*", &x := 0, "int*", &y := 0, "int*", &w := 0, "int*", &h := 0, "ptr", varChild, "int")
            return hwndFocus
    }
    if iUIAutomation && eleFocus {
        ; use IUIAutomationTextPattern2::GetCaretRange
        if ComCall(16, eleFocus, "int", 10024, "ptr*", textPattern2 := ComValue(13, 0), "int") || !textPattern2.Ptr
            goto useGetSelection
        if ComCall(10, textPattern2, "int*", &isActive := 0, "ptr*", caretTextRange := ComValue(13, 0), "int") || !caretTextRange.Ptr || !isActive
            goto useGetSelection
        if !ComCall(10, caretTextRange, "ptr*", &rects := 0, "int") && rects && (rects := ComValue(0x2005, rects, 1)).MaxIndex() >= 3 {
            x := rects[0], y := rects[1], w := rects[2], h := rects[3]
            return hwndFocus
        }
        useGetSelection:
        ; use IUIAutomationTextPattern::GetSelection
        if textPattern2.Ptr
            textPattern := textPattern2
        else if ComCall(16, eleFocus, "int", 10014, "ptr*", textPattern := ComValue(13, 0), "int") || !textPattern.Ptr
            goto useGUITHREADINFO
        if ComCall(5, textPattern, "ptr*", selectionRangeArray := ComValue(13, 0), "int") || !selectionRangeArray.Ptr
            goto useGUITHREADINFO
        if ComCall(3, selectionRangeArray, "int*", &length := 0, "int") || length <= 0
            goto useGUITHREADINFO
        if ComCall(4, selectionRangeArray, "int", 0, "ptr*", selectionRange := ComValue(13, 0), "int") || !selectionRange.Ptr
            goto useGUITHREADINFO
        if ComCall(10, selectionRange, "ptr*", &rects := 0, "int") || !rects
            goto useGUITHREADINFO
        rects := ComValue(0x2005, rects, 1)
        if rects.MaxIndex() < 3 {
            if ComCall(6, selectionRange, "int", 0, "int") || ComCall(10, selectionRange, "ptr*", &rects := 0, "int") || !rects
                goto useGUITHREADINFO
            rects := ComValue(0x2005, rects, 1)
            if rects.MaxIndex() < 3
                goto useGUITHREADINFO
        }
        x := rects[0], y := rects[1], w := rects[2], h := rects[3]
        return hwndFocus
    }
    useGUITHREADINFO:
    if hwndCaret := NumGet(guiThreadInfo, A_PtrSize == 8 ? 48 : 28, "ptr") {
        if DllCall("GetWindowRect", "ptr", hwndCaret, "ptr", clientRect := Buffer(16)) {
            w := NumGet(guiThreadInfo, 64, "int") - NumGet(guiThreadInfo, 56, "int")
            h := NumGet(guiThreadInfo, 68, "int") - NumGet(guiThreadInfo, 60, "int")
            DllCall("ClientToScreen", "ptr", hwndCaret, "ptr", guiThreadInfo.Ptr + 56)
            x := NumGet(guiThreadInfo, 56, "int")
            y := NumGet(guiThreadInfo, 60, "int")
            return hwndCaret
        }
    }
    return 0
    static init() {
        try
            iUIAutomation := ComObject("{E22AD333-B25F-460C-83D0-0581107395C9}", "{30CBE57D-D9D0-452A-AB13-7AC5AC4825EE}")
        hOleacc := DllCall("LoadLibraryW", "str", "Oleacc.dll", "ptr")
        NumPut("int64", 0x11CF3C3D618736E0, "int64", 0x719B3800AA000C81, IID_IAccessible := Buffer(16))
        guiThreadInfo := Buffer(A_PtrSize == 8 ? 72 : 48), NumPut("uint", guiThreadInfo.Size, guiThreadInfo)
    }
}

涛涛涛 最后更新于 2025/8/20

回复内容
暂无回复
回复主贴