注
このドキュメントは、System.Windows.Automation 名前空間で定義されているマネージド UI オートメーション クラスを使用する .NET Framework 開発者を対象としています。 UI オートメーションの最新情報については、Windows Automation API の「UI オートメーション」を参照してください。
このセクションでは、カスタム コントロール用のサーバー側 UI オートメーション プロバイダーを実装する方法について説明します。
Windows Presentation Foundation (WPF) 要素と WPF 以外の要素 (Windows フォーム用に設計されたものなど) の実装は根本的に異なります。 WPF 要素は、 AutomationPeerから派生したクラスを通じて UI オートメーションをサポートします。 WPF 以外の要素は、プロバイダー インターフェイスの実装を通じてサポートを提供します。
セキュリティに関する考慮事項
プロバイダーは、部分信頼環境で動作できるように記述する必要があります。 UIAutomationClient.dll は部分信頼で実行するように構成されていないため、プロバイダー コードはそのアセンブリを参照しないでください。 その場合、コードは完全信頼環境で実行される可能性がありますが、部分信頼環境では失敗します。
特に、 AutomationElementのフィールドなど、UIAutomationClient.dll のクラスのフィールドは使用しないでください。 代わりに、 AutomationElementIdentifiersなど、UIAutomationTypes.dllのクラスの同等のフィールドを使用します。
Windows Presentation Foundation 要素によるプロバイダーの実装
このトピックの詳細については、「 WPF カスタム コントロールの UI オートメーション」を参照してください。
WPF 以外の要素によるプロバイダーの実装
WPF フレームワークの一部ではないが、マネージド コードで記述されたカスタム コントロール (ほとんどの場合は Windows フォーム コントロール) は、インターフェイスを実装することで UI オートメーションのサポートを提供します。 すべての要素は、次のセクションの最初の表に示すインターフェイスの少なくとも 1 つを実装する必要があります。 さらに、要素が 1 つ以上のコントロール パターンをサポートしている場合は、各コントロール パターンに適切なインターフェイスを実装する必要があります。
UI オートメーション プロバイダー プロジェクトは、次のアセンブリを参照する必要があります。
UIAutomationProviders.dll
UIAutomationTypes.dll
WindowsBase.dll
プロバイダー インターフェイス
すべての UI オートメーション プロバイダーは、次のいずれかのインターフェイスを実装する必要があります。
| インターフェイス | 説明 |
|---|---|
| IRawElementProviderSimple | コントロール パターンとプロパティのサポートなど、ウィンドウでホストされる単純なコントロールの機能を提供します。 |
| IRawElementProviderFragment | IRawElementProviderSimpleから継承します。 フラグメント内のナビゲーション、フォーカスの設定、要素の境界矩形の取得など、複雑なコントロール内の要素に機能を追加します。 |
| IRawElementProviderFragmentRoot | IRawElementProviderFragmentから継承します。 指定した座標で子要素を検索し、コントロール全体のフォーカス状態を設定するなど、複雑なコントロールのルート要素の機能を追加します。 |
次のインターフェイスは追加の機能を提供しますが、実装する必要はありません。
| インターフェイス | 説明 |
|---|---|
| IRawElementProviderAdviseEvents | プロバイダーがイベントの要求を追跡できるようにします。 |
| IRawElementProviderHwndOverride | フラグメントの UI オートメーション ツリー内でウィンドウ ベースの要素の位置を変更できるようにします。 |
System.Windows.Automation.Provider名前空間内の他のすべてのインターフェイスは、コントロール パターンのサポート用です。
WPF 以外のプロバイダーの要件
UI オートメーションと通信するには、コントロールで次の主な機能領域を実装する必要があります。
| 機能 | Implementation |
|---|---|
| プロバイダーを UI オートメーションに公開する | コントロール ウィンドウに送信されたWM_GETOBJECT メッセージに応答して、 IRawElementProviderSimple (または派生インターフェイス) を実装するオブジェクトを返します。 フラグメントの場合、これはフラグメント ルートのプロバイダーである必要があります。 |
| プロパティ値を指定する | 値を指定またはオーバーライドする GetPropertyValue を実装します。 |
| クライアントがコントロールと対話できるようにする | IInvokeProviderなどのコントロール パターンをサポートするインターフェイスを実装します。 GetPatternProviderの実装でこれらのパターン プロバイダーを返します。 |
| イベントを発生させる | クライアントがリッスンできるイベントを発生させるために、 AutomationInteropProvider のいずれかの静的メソッドを呼び出します。 |
| フラグメント内でナビゲーションとフォーカスを有効にする | フラグメント内の各要素に対して IRawElementProviderFragment を実装します。 (フラグメントの一部ではない要素には必要ありません)。 |
| フラグメント内の子要素のフォーカスと位置を有効にする | IRawElementProviderFragmentRootを実装します。 (フラグメント ルートではない要素には必要ありません)。) |
WPF 以外のプロバイダーのプロパティ値
カスタム コントロールの UI オートメーション プロバイダーは、オートメーション システムおよびクライアント アプリケーションで使用できる特定のプロパティをサポートする必要があります。 ウィンドウ (HWND) でホストされている要素の場合、UI オートメーションは既定のウィンドウ プロバイダーからいくつかのプロパティを取得できますが、カスタム プロバイダーから他のプロパティを取得する必要があります。
HWND ベースのコントロールのプロバイダーは、通常、次のプロパティを指定する必要はありません (フィールド値で識別されます)。
注
ウィンドウでホストされる単純な要素またはフラグメント ルートの RuntimeIdProperty は、ウィンドウから取得されます。ただし、ルートの下のフラグメント要素 (リスト ボックス内のリスト アイテムなど) は、独自の識別子を提供する必要があります。 詳細については、GetRuntimeIdを参照してください。
Windows フォーム コントロールでホストされているプロバイダーに対して、 IsKeyboardFocusableProperty を返す必要があります。 この場合、既定のウィンドウ プロバイダーが正しい値を取得できない可能性があります。
通常、 NameProperty はホスト プロバイダーによって提供されます。 たとえば、カスタム コントロールが Controlから派生した場合、その名前はコントロールの Text プロパティから派生します。
コード例については、「 UI オートメーション プロバイダーからのプロパティの戻り値」を参照してください。
WPF 以外のプロバイダーのイベント
UI オートメーション プロバイダーは、UI の状態の変化をクライアント アプリケーションに通知するイベントを発生させる必要があります。 イベントの発生には、次のメソッドが使用されます。
| メソッド | 説明 |
|---|---|
| RaiseAutomationEvent | コントロール パターンによってトリガーされるイベントなど、さまざまなイベントを発生させます。 |
| RaiseAutomationPropertyChangedEvent | UI オートメーション プロパティが変更されたときにイベントを発生させます。 |
| RaiseStructureChangedEvent | UI オートメーション ツリーの構造が変更されたときにイベントを発生させます。たとえば、要素の削除や追加などです。 |
イベントの目的は、UI オートメーション システム自体によってアクティビティがトリガーされるかどうかにかかわらず、ユーザー インターフェイス (UI) で何かが発生したことをクライアントに通知することです。 たとえば、 InvokedEvent によって識別されるイベントは、直接ユーザー入力を介して、または Invokeを呼び出すクライアント アプリケーションによって、コントロールが呼び出されるたびに発生する必要があります。
パフォーマンスを最適化するために、プロバイダーは選択的にイベントを発生させるか、受信するクライアント アプリケーションが登録されていない場合はイベントをまったく発生させなくなります。 最適化には次のメソッドが使用されます。
| メソッド | 説明 |
|---|---|
| ClientsAreListening | この静的プロパティは、クライアント アプリケーションが UI オートメーション イベントをサブスクライブしたかどうかを指定します。 |
| IRawElementProviderAdviseEvents | フラグメント ルートでのこのインターフェイスのプロバイダーの実装により、クライアントがフラグメント上のイベントのイベント ハンドラーを登録および登録解除するときに、このインターフェイスを推奨できます。 |
WPF 以外のプロバイダー ナビゲーション
ウィンドウ (HWND) でホストされるカスタム ボタンなどの単純なコントロールのプロバイダーは、UI オートメーション ツリー内のナビゲーションをサポートする必要はありません。 要素との間のナビゲーションは、ホスト ウィンドウの既定のプロバイダーによって処理されます。これは、 HostRawElementProviderの実装で指定されています。 ただし、複雑なカスタム コントロールのプロバイダーを実装する場合は、フラグメントとその子孫のルート ノード間、および兄弟ノード間のナビゲーションをサポートする必要があります。
注
ルート以外のフラグメントの要素は、ウィンドウに直接ホストされていないため、nullからHostRawElementProvider参照を返す必要があります。これには、デフォルトのプロバイダーではナビゲーションのサポートができないという理由があります。
フラグメントの構造は、 Navigateの実装によって決まります。 各フラグメントから可能な方向ごとに、このメソッドは、その方向の要素のプロバイダー オブジェクトを返します。 その方向に要素がない場合、メソッドは null 参照を返します。
フラグメント ルートでは、子要素へのナビゲーションのみがサポートされます。 たとえば、リスト ボックスは、方向が FirstChildの場合はリストの最初の項目を返し、方向が LastChild場合は最後の項目を返します。 フラグメント ルートは、親または兄弟へのナビゲーションをサポートしていません。これはホスト ウィンドウ プロバイダーによって処理されます。
ルートではないフラグメントの要素は、親と兄弟、そして子へのナビゲーションをサポートする必要があります。
非WPFプロバイダーの再親化
ポップアップ ウィンドウは実際には最上位レベルのウィンドウであるため、既定ではデスクトップの子として UI オートメーション ツリーに表示されます。 ただし、多くの場合、ポップアップ ウィンドウは論理的に他のコントロールの子です。 たとえば、コンボ ボックスのドロップダウン リストは、論理的にはコンボ ボックスの子です。 同様に、メニュー ポップアップ ウィンドウは論理的にはメニューの子です。 UI オートメーションは、ポップアップ ウィンドウを関連するコントロールの子ウィンドウとして見せるために、親ウィンドウの再割り当てのサポートを提供します。
ポップアップ ウィンドウを親に変更するには:
ポップアップ ウィンドウのプロバイダーを作成します。 そのためには、ポップアップ ウィンドウのクラスが事前に認識されている必要があります。
それ自体のコントロールであるかのように、そのポップアップに対して通常どおりすべてのプロパティとパターンを実装します。
パラメーターがポップアップ ウィンドウのウィンドウ ハンドルであるHostRawElementProviderから取得した値を返すように、HostProviderFromHandle プロパティを実装します。
ポップアップ ウィンドウとその親の Navigate を実装して、論理親から論理子、および兄弟の子間でナビゲーションが適切に処理されるようにします。
UI オートメーションは、ポップアップ ウィンドウを検出すると、ナビゲーションが既定からオーバーライドされていることを認識し、デスクトップの子として検出されたときにポップアップ ウィンドウをスキップします。 代わりに、ノードはフラグメントを介してのみ到達できます。
親の変更は、コントロールが任意のクラスのウィンドウをホストできる場合には適していません。 たとえば、鉄筋はバンド内で任意の種類の HWND をホストできます。 このような場合に対処するために、UI オートメーションは、次のセクションで説明するように、代替形式の HWND 再配置をサポートします。
WPF 以外のプロバイダーの位置変更
UI オートメーション フラグメントには、それぞれウィンドウ (HWND) に含まれる 2 つ以上の要素を含めることができます。 各 HWND には、HWND を含む HWND の子と見なされる独自の既定のプロバイダーがあるため、UI オートメーション ツリーでは、既定では、フラグメント内の HWND が親ウィンドウの子として表示されます。 ほとんどの場合、これは望ましい動作ですが、UI の論理構造と一致しないため、混乱を招く可能性があります。
この良い例は、鉄筋コントロールです。 鉄筋にはバンドが含まれ、それぞれのバンドには、ツールバー、編集ボックス、コンボ ボックスなどの HWND ベースのコントロールを含めることができます。 リバー HWND の既定のウィンドウ プロバイダーは、バンドコントロールの HWND を子として表示し、リバープロバイダーはバンドを子として表示します。 HWND プロバイダーとリーバープロバイダーは同時に協力して作業し、子を組み合わせるために働いているため、バンドと HWND に基づくコントロールの両方がリーバーの子として表示されます。 ただし、論理的には、鉄筋の子として表示されるのはバンドだけであり、各バンド プロバイダーは、それに含まれるコントロールの既定の HWND プロバイダーと結合する必要があります。
これを実現するために、鉄筋のフラグメント ルート プロバイダーは、バンドを表す一連の子を公開します。 各バンドには、プロパティとパターンを公開できる 1 つのプロバイダーがあります。 HostRawElementProviderの実装では、バンド プロバイダーはコントロール HWND の既定のウィンドウ プロバイダーを返します。このプロバイダーは、HostProviderFromHandleを呼び出して取得し、コントロールのウィンドウ ハンドルを渡します。 最後に、鉄筋のフラグメント ルート プロバイダーは、 IRawElementProviderHwndOverride インターフェイスを実装し、 GetOverrideProviderForHwnd の実装では、指定された HWND に含まれるコントロールの適切なバンド プロバイダーを返します。