如何找到任何活动应用程序的闪烁光标位置?

时间:2014-09-01 17:28:35

标签: objective-c macos cocoa

我正在为Mac OS开发应用程序,我想找到当前应用程序的文本光标(插入符号导航)的位置? 到目前为止,我已经让它要求访问权限,我也可以监视keyEvents,但是如何找到闪烁的光标位置?

(我没有找到鼠标光标位置,我想要text cursor / caret navigation

1 个答案:

答案 0 :(得分:1)

您将需要使用辅助功能API来执行此操作。 这是很多丑陋的丑陋代码,它可能并不总是有效,具体取决于这些应用程序视图中的视图层次结构和可访问性支持程度。 非Cocoa应用程序可能会出现问题而且无法正常工作。 使用WebKit进行渲染的视图也会呈现整个html辅助功能挑战! :)

我从Bogdan Popescu那里得到了这个片段,他制作了Dash。 不要直接复制和粘贴此代码。 研究它,看看API文档对每个函数和类型的说法,并从中慢慢构建一些东西。 理解AX API并使用它们需要花费大量时间。通用方式使用它们需要更长的时间。 它是Core Foundation样式C,与您在Cocoa Objective-C中可能使用的内容大不相同。

CFTypeRef system = nil;
system = AXUIElementCreateSystemWide();
CFTypeRef application = nil;
CFTypeRef focusedElement = nil;
CFRange cfrange;
AXValueRef rangeValue = nil;
// Find the currently focused application
if(AXUIElementCopyAttributeValue(system, kAXFocusedApplicationAttribute, &application) == kAXErrorSuccess)
{
    // Find the currently focused UI Element
    if(AXUIElementCopyAttributeValue(application, kAXFocusedUIElementAttribute, &focusedElement) == kAXErrorSuccess)
    {
        // Get the range attribute of the selected text (i.e. the cursor position)
        if(AXUIElementCopyAttributeValue(focusedElement, kAXSelectedTextRangeAttribute, (CFTypeRef *)&rangeValue) == kAXErrorSuccess)
        {
            // Get the actual range from the range attribute
            if(AXValueGetValue(rangeValue, kAXValueCFRangeType, (void *)&cfrange))
            {
                CFTypeRef bounds = nil;
                textRect = NSZeroRect;
                if(AXUIElementCopyParameterizedAttributeValue(focusedElement, kAXBoundsForRangeParameterizedAttribute, rangeValue, (CFTypeRef *)&bounds) == kAXErrorSuccess)
                {
                    CGRect screenRect;
                    AXValueGetValue(bounds, kAXValueCGRectType, &screenRect);
                    if(bounds)
                    {
                        textRect = [DHAbbreviationManager cocoaRectFromCarbonScreenRect:screenRect];
                        CFRelease(bounds);
                    }
                }
            }
            if(rangeValue)
            {
                CFRelease(rangeValue);
            }
        }
    }
    if(focusedElement)
    {
        CFRelease(focusedElement);
    }
}
if(application)
{
    CFRelease(application);
}
if(system)
{
    CFRelease(system);
}

将AX点从Carbon转换为Cocoa屏幕点。

+ (NSPoint)cocoaScreenPointFromCarbonScreenPoint:(NSPoint)carbonPoint
{
   return NSMakePoint(carbonPoint.x, [[[NSScreen screens] objectAtIndex:0] frame].size.height - carbonPoint.y);
}

研究这些内容。

您还需要深入研究Xcode附带的辅助功能检查器应用,以及来自Apple的类似示例代码 UIElementInspector