サーバー側 UI オートメーション プロバイダの実装

更新 : 2007 年 11 月

ここでは、カスタム コントロールのサーバー側 UI オートメーション プロバイダを実装する方法について説明します。

Windows Presentation Foundation (WPF) 要素の実装と非 WPF 要素 (Windows フォーム用に設計された要素など) の実装は機能的に異なります。WPF 要素は、AutomationPeer の派生クラスを通じて UI オートメーションをサポートします。非 WPF 要素は、プロバイダ インターフェイスの実装を通じてサポートします。

このトピックには次のセクションが含まれています。

  • セキュリティの考慮事項
  • Windows Presentation Foundation 要素によるプロバイダの実装
  • 非 WPF 要素によるプロバイダの実装
  • 関連トピック

セキュリティの考慮事項

プロバイダは、部分信頼環境で動作できるように、書き込まれる必要があります。UIAutomationClient.dll は部分信頼で実行されるように構成されていないため、プロバイダ コードはそのアセンブリを参照しないようにする必要があります。この場合、コードが完全信頼環境で実行されても、その後、部分信頼環境で失敗する可能性があります。

特に、UIAutomationClient.dll 内のクラス (AutomationElement など) のフィールドを使用しないでください。代わりに、UIAutomationTypes.dll 内のクラス (AutomationElementIdentifiers など) の等価のフィールドを使用してください。

Windows Presentation Foundation 要素によるプロバイダの実装

このトピックの詳細については、「WPF カスタム コントロールの UI オートメーション」を参照してください。

非 WPF 要素によるプロバイダの実装

WPF フレームワークの一部でないにもかかわらず、マネージ コードで記述されているカスタム コントロール (ほとんどの場合、Windows フォーム コントロール) は、インターフェイスを実装することにより UI オートメーションをサポートします。すべての要素は、次のセクションの最初の表に記載されているインターフェイスのうち、少なくとも 1 つを実装する必要があります。さらに、1 つ以上のコントロール パターンをサポートする要素は、各コントロール パターンに適したインターフェイスを実装する必要があります。

UI オートメーション プロバイダのプロジェクトでは、次のアセンブリを参照する必要があります。

  • UIAutomationProviders.dll

  • UIAutomationTypes.dll

  • WindowsBase.dll

このセクションには次のサブセクションが含まれています。

  • プロバイダ インターフェイス
  • 非 WPF プロバイダの要件
  • 非 WPF プロバイダのプロパティ値
  • 非 WPF プロバイダのイベント
  • 非 WPF プロバイダのナビゲーション
  • 非 WPF プロバイダの親の再指定
  • 非 WPF プロバイダの再配置

プロバイダ インターフェイス

すべての UI オートメーション プロバイダは、次のインターフェイスのいずれかを実装する必要があります。

インターフェイス

説明

IRawElementProviderSimple

コントロール パターンおよびプロパティのサポートなどの機能を、ウィンドウでホストされる単純なコントロールに提供します。

IRawElementProviderFragment

IRawElementProviderSimple から継承します。フラグメント内のナビゲーション機能、フォーカス設定機能、要素の外接する四角形を返す機能など、複合コントロール内の要素の機能を追加します。

IRawElementProviderFragmentRoot

IRawElementProviderFragment から継承します。指定した座標への子要素の配置、コントロール全体のフォーカス状態の設定などの機能を、複雑なコントロールのルート要素に追加します。

次のインターフェイスは、実装が必須ではない追加機能を提供します。

インターフェイス

説明

IRawElementProviderAdviseEvents

プロバイダがイベントの要求を追跡できるようにします。

IRawElementProviderHwndOverride

フラグメントの UI オートメーション ツリー内でウィンドウ ベースの要素を再配置できるようにします。

System.Windows.Automation.Provider 名前空間に含まれる他のインターフェイスはすべて、コントロール パターンのサポート用です。

非 WPF プロバイダの要件

UI オートメーション と通信するには、コントロールで次の機能のメイン エリアを実装する必要があります。

機能

実装

UI オートメーションへのプロバイダの公開

コントロール ウィンドウに送信された WM_GETOBJECT メッセージに対する応答として、IRawElementProviderSimple を実装するオブジェクト (または派生インターフェイス) を返します。フラグメントの場合、これはフラグメント ルートのプロバイダである必要があります。

プロパティ値の指定

値を指定またはオーバーライドするために GetPropertyValue を実装します。

クライアントとコントロールの対話の有効化

コントロール パターンをサポートするインターフェイス (IInvokeProvider など) を実装します。GetPatternProvider の実装でこれらのパターン プロバイダを返します。

イベントの発生

AutomationInteropProvider の静的メソッドのいずれかを呼び出して、クライアントがリッスンできるイベントを発生させます。

フラグメント内のナビゲーションとフォーカス設定の有効化

フラグメント内の各要素を表す IRawElementProviderFragment を実装します (フラグメントに含まれない要素については必要ありません)。

フラグメント内の子要素のフォーカス設定および配置の有効化

IRawElementProviderFragmentRoot を実装します (フラグメント ルートでない要素については必要ありません)。

非 WPF プロバイダのプロパティ値

カスタム コントロールの UI オートメーション プロバイダは、オートメーション システムおよびクライアント アプリケーションで使用可能な特定のプロパティをサポートする必要があります。ウィンドウ (HWND) でホストされる要素の場合、UI オートメーションは、一部のプロパティを既定のウィンドウ プロバイダから取得できますが、その他のプロパティについてはカスタム プロバイダから取得する必要があります。

HWND ベースのコントロールのプロバイダは、通常、次のプロパティ (フィールド値で識別されます) を提供する必要はありません。

ms748277.alert_note(ja-jp,VS.90).gifメモ :

ウィンドウでホストされる単純な要素やフラグメント ルートの RuntimeIdProperty はウィンドウから取得されます。ただし、ルートの下のフラグメント要素 (リスト ボックス内のリスト項目など) は、それ自体の識別子を提供する必要があります。詳細については、GetRuntimeId を参照してください。

Windows フォーム コントロールでホストされるプロバイダの場合は、IsKeyboardFocusableProperty が返されます。この場合、既定のウィンドウ プロバイダは、正確な値を取得できない可能性があります。

NameProperty は、通常、ホスト プロバイダによって指定されます。たとえば、カスタム コントロールが Control から派生する場合、その名前はコントロールの Text プロパティから派生します。

コード例については、「UI オートメーション プロバイダからのプロパティの返却」を参照してください。

非 WPF プロバイダのイベント

UI オートメーション プロバイダは、UI の状態が変更されたことをクライアント アプリケーションに通知するためにイベントを発生させる必要があります。イベントを発生させるために次のメソッドが使用されます。

メソッド

説明

RaiseAutomationEvent

コントロール パターンによってトリガされたイベントを含むさまざまなイベントを発生させます。

RaiseAutomationPropertyChangedEvent

UI オートメーション プロパティが変更された場合にイベントを発生させます。

RaiseStructureChangedEvent

要素の追加または削除などによって UI オートメーション ツリーの構造が変更された場合にイベントを発生させます。

イベントの目的は、UI オートメーション システム自体がアクティビティをトリガするかどうかにかかわらず、ユーザー インターフェイス (UI) で何かが発生したことをクライアントに通知することです。たとえば、コントロールは、ユーザーの直接入力で呼び出される場合とクライアント アプリケーションの Invoke 呼び出しによって呼び出される場合がありますが、いずれの場合も InvokedEvent で識別されるイベントを発生させる必要があります。

プロバイダは、パフォーマンスを最適化するために、イベントを選択的に発生させることができます。また、イベントを受信するクライアント アプリケーションが登録されていない場合は、イベントがまったく発生しないようにすることもできます。最適化のために次のメソッドが使用されます。

メソッド

説明

ClientsAreListening

この静的プロパティは、UI オートメーション イベントにサブスクライブしているクライアント アプリケーションがあるかどうかを示します。

IRawElementProviderAdviseEvents

プロバイダでこのインターフェイスをフラグメント ルートに実装すると、クライアントがフラグメントのイベントにイベント ハンドラを登録および登録解除したときに、フラグメント ルートに通知されるようになります。

非 WPF プロバイダのナビゲーション

ウィンドウ (HWND) でホストされるカスタム ボタンなどの単純なコントロールのプロバイダは、UI オートメーション ツリー内でのナビゲーションをサポートする必要はありません。要素間のナビゲーションは、HostRawElementProvider の実装で指定された、ホスト ウィンドウの既定のプロバイダによって処理されます。ただし、カスタム複合コントロールのプロバイダを実装する場合は、フラグメントのルート ノードとその子孫の間のナビゲーション、および兄弟ノード間のナビゲーションをサポートする必要があります。

ms748277.alert_note(ja-jp,VS.90).gifメモ :

フラグメントのルート以外の要素はウィンドウで直接ホストされず、既定のプロバイダはこれらの要素間のナビゲーションをサポートしません。したがって、これらの要素は、HostRawElementProvider から null 参照を返す必要があります。

フラグメントの構造は Navigate の実装によって決定されます。このメソッドは、各フラグメントからの方向ごとに、その方向の要素のプロバイダ オブジェクトを返します。その方向に要素が存在しない場合、このメソッドは null 参照を返します。

フラグメント ルートは、子要素へのナビゲーションのみをサポートします。たとえば、リスト ボックスは、方向が FirstChild の場合はリスト内の最初の項目を返し、方向が LastChild の場合は最後の項目を返します。フラグメント ルートは、親または兄弟へのナビゲーションをサポートしません。これはホスト ウィンドウのプロバイダで処理されます。

フラグメントのルート以外の要素は、親、兄弟、および子へのナビゲーションをサポートする必要があります。

非 WPF プロバイダの親の再指定

ポップアップ ウィンドウは、実際にはトップレベル ウィンドウであるため、既定でデスクトップの子として UI オートメーション ツリーに表示されます。ただし、多くの場合、ポップアップ ウィンドウは他のコントロールの論理的な子です。たとえば、コンボ ボックスのドロップダウン リストはコンボ ボックスの論理的な子です。同様に、メニュー ポップアップ ウィンドウはメニューの論理的な子です。UI オートメーションは、ポップアップ ウィンドウが関連するコントロールの子として表示されるようにするために、ポップアップ ウィンドウの親の再指定をサポートします。

ポップアップ ウィンドウの親を再指定するには、次の手順を実行します。

  1. ポップアップ ウィンドウのプロバイダを作成します。これを行うには、ポップアップ ウィンドウのクラスを事前に知る必要があります。

  2. このポップアップ自体が 1 つのコントロールであるかのように、ポップアップの通常のプロパティとパターンをすべて実装します。

  3. HostRawElementProvider プロパティを実装し、HostProviderFromHandle (パラメータはポップアップ ウィンドウのウィンドウ ハンドル) から取得した値を返すようにします。

  4. ポップアップ ウィンドウとその親の Navigate を実装し、論理上の親から論理上の子へのナビゲーションと兄弟の子の間のナビゲーションが適切に処理されるようにします。

UI オートメーションは、ポップアップ ウィンドウを検出すると、既定のナビゲーションがオーバーライドされていると認識し、デスクトップの子として検出されたポップアップ ウィンドウをスキップします。代わりに、このノードはフラグメント経由でのみ到達可能になります。

親の再指定は、コントロールが任意のクラスのウィンドウをホストできる場合には適していません。たとえば、rebar は任意の種類の HWND をそのバンド内にホストできます。UI オートメーションは、これらのケースを処理するために、次のセクションで説明する代替形式の HWND 再配置をサポートします。

非 WPF プロバイダの再配置

UI オートメーションフラグメントは、別々のウィンドウ (HWND) に格納される複数の要素を格納する場合があります。各 HWND には、その HWND を格納 HWND の子と見なす既定のプロバイダがあります。そのため、既定では、フラグメントの HWND が親ウィンドウの子として UI オートメーション ツリーに表示されます。ほとんどの場合、これは望ましい動作ですが、UI の論理構造に一致しないため、混乱を招く可能性もあります。

この良い例は rebar コントロールです。rebar はバンドを格納し、各バンドはツール バー、編集ボックス、コンボ ボックスなど HWND ベースのコントロールを格納します。rebar HWND の既定のウィンドウ プロバイダはバンド コントロール HWND を子と見なし、rebar プロバイダはバンドを子と見なします。HWND プロバイダと rebar プロバイダは連携して動作し、それぞれの子を結合します。そのため、バンドと HWND ベースのコントロールは rebar の子として表示されます。ただし、論理的には、バンドのみが rebar の子として表示され、各バンド プロバイダは、バンドに格納されるコントロールの既定の HWND プロバイダと結合される必要があります。

これを実現するために、rebar のフラグメント ルート プロバイダは、バンドを表す一連の子を公開しています。各バンドには、プロパティおよびパターンを公開できる単一のプロバイダがあります。バンド プロバイダは、HostRawElementProvider の実装で、コントロール HWND の既定のウィンドウ プロバイダを返します。このウィンドウ プロバイダは、HostProviderFromHandle にコントロールのウィンドウ ハンドルを渡して呼び出すことによって取得されます。最後に、rebar のフラグメント ルート プロバイダは、IRawElementProviderHwndOverride インターフェイスを実装し、GetOverrideProviderForHwnd の実装で、指定された HWND に格納されているコントロールの適切なバンド プロバイダを返します。

参照

処理手順

サーバー側 UI オートメーション プロバイダの公開

UI オートメーション プロバイダからのプロパティの返却

UI オートメーション プロバイダからのイベントの発生

UI オートメーション フラグメント プロバイダでのナビゲーションの有効化

UI オートメーション プロバイダでのコントロール パターンのサポート

簡単なプロバイダのサンプル

フラグメント プロバイダのサンプル

概念

UI オートメーション プロバイダの概要