如何通过辅助功能API获取当前所选文本的全局屏幕坐标.

Ami*_*Sri 13 cocoa accessibility screen objective-c selectedtext

我需要帮助才能找到,在任何应用程序上按CMD + CTRL + D时,Dictionary应用程序如何显示以下弹出对话框中的所选文本.我想为我的cocoa应用程序实现相同类型的功能,我的应用程序将在后台运行,并在所选文本的某些热键按下时显示建议.

字典应用程序热键建议对话框

我已经实现了热键捕获,我只需要有代码来获取屏幕上所选文本的矩形区域,所以我可以像字典应用程序一样显示对话框.

谢谢

omz*_*omz 16

您可以使用辅助功能API.确保选中"启用辅助设备访问"设置(在"系统偏好设置"/"通用访问"中).

以下代码段将确定大多数应用程序中所选文本的边界(以屏幕坐标为单位).不幸的是,它在Mail和Safari中不起作用,因为它们使用私有辅助功能属性.它也许可以让它在那里工作,但它需要更多的工作和可能的私有API调用.

AXUIElementRef systemWideElement = AXUIElementCreateSystemWide();
AXUIElementRef focussedElement = NULL;
AXError error = AXUIElementCopyAttributeValue(systemWideElement, kAXFocusedUIElementAttribute, (CFTypeRef *)&focussedElement);
if (error != kAXErrorSuccess) {
    NSLog(@"Could not get focussed element");
} else {
    AXValueRef selectedRangeValue = NULL;
    AXError getSelectedRangeError = AXUIElementCopyAttributeValue(focussedElement, kAXSelectedTextRangeAttribute, (CFTypeRef *)&selectedRangeValue);
    if (getSelectedRangeError == kAXErrorSuccess) {
        CFRange selectedRange;
        AXValueGetValue(selectedRangeValue, kAXValueCFRangeType, &selectedRange);
        AXValueRef selectionBoundsValue = NULL;
        AXError getSelectionBoundsError = AXUIElementCopyParameterizedAttributeValue(focussedElement, kAXBoundsForRangeParameterizedAttribute, selectedRangeValue, (CFTypeRef *)&selectionBoundsValue);
        CFRelease(selectedRangeValue);
        if (getSelectionBoundsError == kAXErrorSuccess) {
            CGRect selectionBounds;
            AXValueGetValue(selectionBoundsValue, kAXValueCGRectType, &selectionBounds);
            NSLog(@"Selection bounds: %@", NSStringFromRect(NSRectFromCGRect(selectionBounds)));
        } else {
            NSLog(@"Could not get bounds for selected range");
        }
        if (selectionBoundsValue != NULL) CFRelease(selectionBoundsValue);
    } else {
        NSLog(@"Could not get selected range");
    }
}
if (focussedElement != NULL) CFRelease(focussedElement);
CFRelease(systemWideElement);
Run Code Online (Sandbox Code Playgroud)

  • 坐标垂直翻转。要获得面板的框架,您必须像这样转换 y 坐标:`selectionBounds.origin.y = [[NSScreen mainScreen] frame].size.height - SelectionBounds.origin.y - SelectionBounds.size。 height`(稍微简化一下,假设您只有一个屏幕)。 (3认同)

Bez*_*eel 8

在这里你可以用 Swift 获取 @omz 答案

let systemWideElement = AXUIElementCreateSystemWide()
var focusedElement : AnyObject?

let error = AXUIElementCopyAttributeValue(systemWideElement, kAXFocusedUIElementAttribute as CFString, &focusedElement)
if (error != .success){
    print("Couldn't get the focused element. Probably a webkit application")
} else {
    var selectedRangeValue : AnyObject?
    let selectedRangeError = AXUIElementCopyAttributeValue(focusedElement as! AXUIElement, kAXSelectedTextRangeAttribute as CFString, &selectedRangeValue)
    if (selectedRangeError == .success){
        var selectedRange : CFRange?
        AXValueGetValue(selectedRangeValue as! AXValue, AXValueType(rawValue: kAXValueCFRangeType)!, &selectedRange)
        var selectRect = CGRect()
        var selectBounds : AnyObject?
        let selectedBoundsError = AXUIElementCopyParameterizedAttributeValue(focusedElement as! AXUIElement, kAXBoundsForRangeParameterizedAttribute as CFString, selectedRangeValue!, &selectBounds)
        if (selectedBoundsError == .success){
            AXValueGetValue(selectBounds as! AXValue, .cgRect, &selectRect)
            //do whatever you want with your selectRect
            print(selectRect)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)