NVDA 屏幕 reader 请求错误 QAccessible::InterfaceType

NVDA screen reader requests wrong QAccessible::InterfaceType

我正在使用 Qt 5.9.1。

我正在尝试使应用程序可通过屏幕阅读器访问。我有一个包含文本(很多)的自定义小部件(我们称它为 MyWidget)。文本是使用 QPainter 绘制的,这就是为什么使用自定义小部件而不是 QTextBrowser.

我在派生自 QAccessibleWidgetQAccessibleTextInterfaceAccessibleMyWidget class 中为小部件实现了 QAccessibleTextInterface。它在 Linux 下与 Orca 一起工作正常,但是当在 Windows 7 中与 NVDA 一起使用时,QAccessibleInterface::interface_cast() 请求错误的接口类型。使用 Orca,我收到了 QAccessible::TextInterface 的请求。在 NVDA 中,它总是 QAccessible::ValueInterface.

AccessibleMyWidget 定义为:

class AccessibleMyWidget:
    public QAccessibleWidget, public QAccessibleTextInterface {

public:
    explicit AccessibleMyWidget(QWidget* w)
        : QAccessibleWidget(w, QAccessible::EditableText)
    {
        Q_ASSERT(isValid());
    }

    void* interface_cast(QAccessible::InterfaceType t) override
    {
        if (t == QAccessible::TextInterface) {
            // !!! This is never requested with NVDA !!!
            return static_cast<QAccessibleTextInterface*>(this);
        }
        return QAccessibleWidget::interface_cast(t);
    }

    /*
     * QAccessibleTextInterface implementation below this point.
     */
    void addSelection(int startOffset, int endOffset) override;
    QString attributes(int offset, int* startOffset,
                       int* endOffset) const override;
    // etc.
};

使用 Linux 下的 Orca,一切似乎都按预期进行。我收到 interface_cast()TextInterface 调用,之后调用 QAccessibleTextInterface 的各种函数。在 Linux 下使用 NVDA,我只得到 interface_cast()ValueInterface 的调用,并且 QAccessibleTextInterface 函数的 none 被调用。这意味着 MyWidget 是完全不可访问的,除非我覆盖 QAccessibleWidget::text() 并且只是 return 所有文本作为一个字符串,这意味着没有光标导航,没有选择支持......它基本上变成了一个QLabel 此时,但有大量文本,因此很难使用。

我在这里错过了什么?

好吧,一位 NVDA 开发人员帮助我找到了这个问题。这是因为 Qt 的 MinGW 版本禁用了 IAccessible2,而是使用 MSAA(Microsoft Active Accessibility),它不支持任何这些接口。 IA2需要COM,而MinGW不支持。

所以我必须从 GCC/MinGW 切换到 MSVC 才能在 Windows 上完成这项工作。太糟糕了,在可预见的未来,这实际上不是一个选择:-/

2020 年更新:
从那以后,这已得到修复。不确定确切时间,但当前的 mingw Qt 构建现在支持此功能。