Как получить глобальные экранные координаты выделенного в данный момент текста через API специальных возможностей.

Мне нужна помощь, чтобы узнать, как приложение "Словарь" показывает следующее всплывающее диалоговое окно для выделенного текста при нажатии CMD+CTRL+D в любом приложении. Я хочу реализовать такую ​​же функциональность для моего приложения с какао, где мое приложение будет работать в фоновом режиме и отображать предложения по нажатию горячей клавиши для выбранного текста.

Диалоговое окно с подсказкой приложения словаря

Я уже реализовал захват с помощью горячих клавиш, мне просто нужен код, чтобы получить область прямоугольника выделенного текста на экране, чтобы я мог показывать диалог, как приложение словаря.

Спасибо

2 ответа

Решение

Вы можете использовать специальные 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);

Здесь вы идете для ответа @omz в Swift

    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)
            }
        }
    }

То, что вы ищете, это Сервис. С сервисами ваше приложение даже не должно запускаться или захватывать глобальные горячие клавиши.

Например, функциональность описанного вами словарного приложения на самом деле является службой, которую можно увидеть в меню " Службы".

Словарь Сервисного Меню

Руководство по внедрению услуг Apple, вероятно, является лучшей информацией об услугах.

Другие вопросы по тегам