将 NSAccessibilityElement 添加到现有的 NSView
Add NSAccessibilityElement to an existing NSView
我想在我的应用程序中使用 MacOS accessibility feature,它呈现自己的自定义 UI(即不使用 Cocoa)。为此,我实现了与我绘制的每个小部件相关联的子类 NSAccessibilityElement
树。
根 UI 容器托管在外部提供给我的应用程序的 NSView
中(我的应用程序是一个插件)。现在我需要将 NSAccessibilityElement
的树附加到主机提供的现有 NSView
。
Apple documentation 推荐两种实现方式:
- 重新实现父级的
accessibilityChildren
属性 以包含自定义元素(例如 Qt 使用此方法)。不幸的是,我没有自己创建父 NSView
,它是从外部注入的。
- 调用
accessibilityAddChildElement
便捷方法。但是当我在提供的 NSView
对象上调用它时,我得到一个异常,它不响应这个方法。
将 NSAccessibilityElement
的树附加到现有 NSView
的正确方法是什么?
所以我最终子类化 NSView
以捕获顶层 NSAccessibilityElement
。重写 - (NSArray*) accessibilityChildren
方法 returns 将可访问性元素捕获为其子元素之一:
@interface AccessibilityRootView : NSView
- (instancetype)initWithAccessibilityElement: (NSAccessibilityElement*)anElement;
@end
@implementation AccessibilityRootView
{
NSAccessibilityElement* element;
}
- (instancetype) initWithAccessibilityElement: (NSAccessibilityElement*)anElement
{
self = [super init];
if (self)
element = anElement;
return self;
}
- (NSArray*) accessibilityChildren
{
NSArray<NSAccessibilityElement*> *children = [super accessibilityChildren];
int numKids = (int)[children count] + 1;
NSMutableArray<NSAccessibilityElement*> *kids = [NSMutableArray<NSAccessibilityElement*> arrayWithCapacity:numKids];
for (id object in children)
[kids addObject:object];
[kids addObject: element];
return NSAccessibilityUnignoredChildren (kids);
}
@end
然后我将这个零大小的子类视图附加到主机提供的父 NSView
:
NSView* hostView = /* host-provided NSView */;
AccessibilityRootView* accessibilityRootView = [[AccessibilityRootView alloc] initWithAccessibilityElement:(NSAccessibilityElement*)topLevelAccessibilityElement];
[hostView addSubview:accessibilityRootView];
[accessibilityRootView release];
此时我的所有 NSAccessibilityElements
都附加到主机提供的视图中的那个零大小视图,MacOS 可以成功查询项目。
此外,每个 NSAccessibilityElement
都必须正确实施其
- (NSRect)accessibilityFrame
和
- (id) accessibilityHitTest:(NSPoint)point
以匹配我自定义绘制的 UI 小部件的屏幕位置。
我想在我的应用程序中使用 MacOS accessibility feature,它呈现自己的自定义 UI(即不使用 Cocoa)。为此,我实现了与我绘制的每个小部件相关联的子类 NSAccessibilityElement
树。
根 UI 容器托管在外部提供给我的应用程序的 NSView
中(我的应用程序是一个插件)。现在我需要将 NSAccessibilityElement
的树附加到主机提供的现有 NSView
。
Apple documentation 推荐两种实现方式:
- 重新实现父级的
accessibilityChildren
属性 以包含自定义元素(例如 Qt 使用此方法)。不幸的是,我没有自己创建父NSView
,它是从外部注入的。 - 调用
accessibilityAddChildElement
便捷方法。但是当我在提供的NSView
对象上调用它时,我得到一个异常,它不响应这个方法。
将 NSAccessibilityElement
的树附加到现有 NSView
的正确方法是什么?
所以我最终子类化 NSView
以捕获顶层 NSAccessibilityElement
。重写 - (NSArray*) accessibilityChildren
方法 returns 将可访问性元素捕获为其子元素之一:
@interface AccessibilityRootView : NSView
- (instancetype)initWithAccessibilityElement: (NSAccessibilityElement*)anElement;
@end
@implementation AccessibilityRootView
{
NSAccessibilityElement* element;
}
- (instancetype) initWithAccessibilityElement: (NSAccessibilityElement*)anElement
{
self = [super init];
if (self)
element = anElement;
return self;
}
- (NSArray*) accessibilityChildren
{
NSArray<NSAccessibilityElement*> *children = [super accessibilityChildren];
int numKids = (int)[children count] + 1;
NSMutableArray<NSAccessibilityElement*> *kids = [NSMutableArray<NSAccessibilityElement*> arrayWithCapacity:numKids];
for (id object in children)
[kids addObject:object];
[kids addObject: element];
return NSAccessibilityUnignoredChildren (kids);
}
@end
然后我将这个零大小的子类视图附加到主机提供的父 NSView
:
NSView* hostView = /* host-provided NSView */;
AccessibilityRootView* accessibilityRootView = [[AccessibilityRootView alloc] initWithAccessibilityElement:(NSAccessibilityElement*)topLevelAccessibilityElement];
[hostView addSubview:accessibilityRootView];
[accessibilityRootView release];
此时我的所有 NSAccessibilityElements
都附加到主机提供的视图中的那个零大小视图,MacOS 可以成功查询项目。
此外,每个 NSAccessibilityElement
都必须正确实施其
- (NSRect)accessibilityFrame
和
- (id) accessibilityHitTest:(NSPoint)point
以匹配我自定义绘制的 UI 小部件的屏幕位置。