次の方法で共有


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

メモメモ

このドキュメントは、System.Windows.Automation 名前空間で定義されているマネージ UI Automation クラスを使用する .NET Framework 開発者を対象としています。UI Automationに関する最新情報については、「Windows Automation API: UI Automation (Windows オートメーション API: UI オートメーション)」を参照してください。

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

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

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

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

セキュリティの考慮事項

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

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

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

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

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

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

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

  • UIAutomationProviders.dll

  • UIAutomationTypes.dll

  • WindowsBase.dll

ここでは、次の項目について説明します。

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

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

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

インターフェイス

説明

IRawElementProviderSimple

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

IRawElementProviderFragment

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

IRawElementProviderFragmentRoot

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

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

インターフェイス

説明

IRawElementProviderAdviseEvents

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

IRawElementProviderHwndOverride

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

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

非 WPF プロバイダーの要件

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

機能

実装

UI Automationへのプロバイダーの公開

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

プロパティ値の指定

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

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

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

イベントの発生

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

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

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

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

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

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

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

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

メモメモ

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

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

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

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

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

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

メソッド

説明

RaiseAutomationEvent

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

RaiseAutomationPropertyChangedEvent

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

RaiseStructureChangedEvent

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

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

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

メソッド

説明

ClientsAreListening

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

IRawElementProviderAdviseEvents

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

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

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

メモメモ

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

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

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

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

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

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

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

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

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

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

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

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

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

非 WPF プロバイダーの再配置

UI Automation フラグメントは、別々のウィンドウ (HWND) に格納される複数の要素を格納する場合があります。 各 HWND には、その HWND を格納 HWND の子と見なす既定のプロバイダーがあります。そのため、既定では、フラグメントの HWND が親ウィンドウの子として UI Automation ツリーに表示されます。 ほとんどの場合、これは望ましい動作ですが、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 オートメーション プロバイダーの概要