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

NSG*_*ode 3 macos cocoa objective-c

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

(我不是在寻找鼠标光标位置,我想要文本光标/插入符号导航

uch*_*aka 6

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

我从制作 Dash 的 Bogdan Popescu 那里得到了这个片段。不要直接复制和粘贴此代码。研究它,看看 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);
}
Run Code Online (Sandbox Code Playgroud)

将 AX 点从 Carbon 转换为 Cocoa Screen 点。

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

研究这些位。

您还需要深入研究Xcode 附带的Accessibility Inspector 应用程序以及来自 Apple 的类似示例代码UIElementInspector