Active Accessibility サーバーへの UI オートメーション機能の追加

Microsoft UI オートメーション プロバイダーを備えていないものの、IAccessible を実装するコントロールは、IAccessibleEx インターフェイスを実装することで、簡単にアップグレードして UI オートメーション機能の一部を提供できます。 このインターフェイスにより、IRawElementProviderFragment などの UI オートメーション プロバイダー インターフェイスを完全に実装する必要なく、コントロールで UI オートメーションのプロパティとコントロール パターンを公開できるようになります。 IAccessibleEx を実装するには、ベースラインの Microsoft Active Accessibility オブジェクト階層にエラーや矛盾 (親オブジェクトに子としてリストされていない子オブジェクトなど) が含まれていたり、その階層が UI オートメーション仕様と競合したりしてはなりません。 Microsoft Active Accessibility オブジェクト階層がこれらの要件を満たしている場合は、IAccessibleEx を使用して機能を追加するのに適しています。満たしていない場合は、UI オートメーションを単独で、または Microsoft Active Accessibility 実装と一緒に実装する必要があります。

範囲の値を持つカスタム コントロールの例を考えてみましょう。 そのコントロールの Microsoft Active Accessibility サーバーはコントロールの役割を定義し、現在の値を返すことはできますが、コントロールの最小値と最大値を返す手段がありません。理由は、これらのプロパティが Microsoft Active Accessibility で定義されていないためです。 UI オートメーション クライアントは、コントロールの役割、現在の値、およびその他の Microsoft Active Accessibility プロパティを取得できます。なぜなら、UI オートメーション コアが IAccessible を通じてこれらを取得できるためです。 ただし、オブジェクトの IRangeValueProvider インターフェイスにアクセスできない場合、UI オートメーションは最大値と最小値を取得することもできません。

コントロール開発者は、コントロールに完全な UI オートメーション プロバイダーを提供することもできますが、これは、ナビゲーションや共通プロパティなど、IAccessible 実装の既存の機能の多くが重複することを意味します。 代わりに、開発者は引き続き IAccessible に依存してこの機能を提供しながら、IRangeValueProvider を通じてコントロール固有のプロパティに対するサポートを追加できます。

カスタム コントロールを更新するには、次の主な手順が必要です。

  • このオブジェクトまたは別のオブジェクトで IAccessibleEx インターフェイスを検出できるように、ユーザー補助の高いオブジェクトに IServiceProvider を実装します。
  • アクセス可能なオブジェクトに IAccessibleEx を実装します。
  • Microsoft Active Accessibility の子項目に個別のアクセス可能なオブジェクトを作成します。これらの子項目は、Microsoft Active Accessibility では親オブジェクトの IAccessible インターフェイスによって表される場合があります (リスト項目など) 。 これらのオブジェクトに IAccessibleEx を実装します。
  • ユーザー補助の高いすべてのオブジェクトに IRawElementProviderSimple を実装します。
  • ユーザー補助の高いオブジェクトに適切なコントロール パターン インターフェイスを実装します。

このトピックは、次のセクションで構成されています。

IAccessibleEx の公開

コントロールの IAccessibleEx の実装は別のオブジェクトに存在する可能性があるため、クライアント アプリケーションはこのインターフェイスを取得するために QueryInterface に依存することはできません。 代わりに、クライアントは IServiceProvider::QueryService を呼び出す必要があります。 このメソッドの実装例では、IAccessibleEx が別のオブジェクトに実装されていないことを前提としています。そのため、メソッドは単にQueryInterface を呼び出します。

HRESULT CListboxAccessibleObject::QueryService(REFGUID guidService, REFIID riid, LPVOID *ppvObject)
{
    if (!ppvObject)
    {
        return E_INVALIDARG;
    }
    *ppvObject = NULL;
    if (guidService == __uuidof(IAccessibleEx))
    {
        return QueryInterface(riid, ppvObject);
    }
    else 
    {
        return E_INVALIDARG;
    }
};

IAccessibleEx の実装

IAccessibleEx のメソッドで最も興味深いのは、GetObjectForChild です。 このメソッドを使用すると、Microsoft Active Accessibility サーバーで、子項目の補助オブジェクト (少なくとも IAccessibleEx を公開するオブジェクト) を作成できます。 Microsoft Active Accessibility では、子項目は通常、補助オブジェクトとしてではなく、補助オブジェクトの子として表されます。 しかし、UI オートメーションでは、各要素を個別の補助オブジェクトで表す必要があるため、GetObjectForChild は、必要に応じて子ごとに個別のオブジェクトを作成する必要があります。

次の実装例は、カスタム リスト ビュー内の項目に対して補助オブジェクトを返します。

HRESULT CListboxAccessibleObject::GetObjectForChild(long idChild, IAccessibleEx **pRetVal)
{ 
    *pRetVal = NULL;
    VARIANT vChild;
    vChild.vt = VT_I4;
    vChild.lVal = idChild;

    // ValidateChildId is an application-defined function that checks whether
    // the child ID is valid. This is similar to code that validates the varChild
    // parameter in IAccessible methods.
    //
    // Additionally, if this idChild corresponds to a child that has its own
    // IAccessible, we should also return E_INVALIDARG here. (The caller
    // should instead be using the IAccessibleEx from that child's own
    // IAccessible in that case.)
    if (idChild == CHILDID_SELF || FAILED(ValidateChildId(vChild)))
    {
        return E_INVALIDARG;
    }

    // Return a suitable provider for this specific child.
    // This implementation returns a new instance each time; an implementation
    // can cache these if desired.

    // _pListboxControl is a member variable pointer to the owning control.
    IAccessibleEx* pAccEx  = new CListItemAccessibleObject(idChild, _pListboxControl);
    if (pAccEx == NULL)
    {
        return E_OUTOFMEMORY;
    }
    *pRetVal = pAccEx;
    return S_OK; 
}

完全なサンプル実装については、「カスタム コントロールを補助にする、パート 5: IAccessibleEx を使用したカスタム コントロールへの UI オートメーション サポートの追加」を参照してください。

UI オートメーション プロバイダー プログラマー ガイド