Text コントロール パターンと TextRange コントロール パターン
プロパティとメソッドに関する情報を含む、 ITextProvider、 ITextProvider2、 および ITextRangeProvider を実装するためのガイドラインと規則について説明します。 Text コントロール パターンを使用すると、アプリケーションとコントロールは単純なテキスト オブジェクト モデルを公開でき、クライアントはテキスト ベースのコントロールからテキスト コンテンツ、テキスト属性、および埋め込みオブジェクトを取得できます。
Text コントロール パターンをサポートするために、コントロールは ITextProvider インターフェイスと ITextProvider2 インターフェイスを実装します。 テキスト コントロール パターンをサポートするコントロールの種類には、編集コントロールとドキュメント コントロールの種類、およびユーザーがテキストを入力したり、読み取り専用テキストを選択したりできるようにするその他のコントロールの種類が含まれます。
テキスト コントロール パターンは、他の Microsoft UI オートメーション コントロール パターンと共に使用して、表、ハイパーリンク、コマンド ボタンなど、テキスト内のいくつかの種類の埋め込みオブジェクトをサポートできます。
ITextProvider インターフェイスと ITextProvider2 インターフェイスには、テキスト範囲を取得するためのメソッドが多数含まれています。 テキスト範囲は、テキスト コンテナー内の連続したテキストのスパン (または複数の非結合のテキストスパン) を表すオブジェクトです。 1 つの ITextProvider メソッドは、文書全体を表すテキスト範囲を取得し、他のメソッドは、選択したテキスト、表示されているテキスト、またはテキストに埋め込まれたオブジェクトなど、ドキュメントの一部を表すテキスト範囲を取得します。
テキスト範囲オブジェクトは、ITextRangeProvider インターフェイスを介して実装される TextRange コントロール パターンによって表されます。 TextRange コントロール パターンは、範囲内のテキストに関する情報を公開したり、範囲のエンドポイントを移動したり、テキストを選択または選択解除したり、範囲をビューにスクロールしたりするために使用されるメソッドとプロパティを提供します。
Text コントロール パターンと TextRange コントロール パターンの詳細については、「テキストコンテンツのUI オートメーションサポート」を参照してください。
以降、Windows 8.1 プロバイダーは ITextRangeProvider2 インターフェイスを実装できます。 これにより、テキスト範囲に関連付けられているコンテキスト メニューを呼び出します。 これは、テキストオートコレクトや入力方法エディター (IME) 候補の選択などのシナリオをサポートします。
このトピックは、次のセクションで構成されています。
実装のガイドラインと規則
Text コントロール パターンを実装する場合は、次のガイドラインと規則に注意してください。
- テキストへのアクセスを可能にするコントロール (テキストの入力や読み取り専用テキストの選択など) は、 Text コントロール パターンをサポートする必要があります。
- Text コントロール パターンは、標準のボタン コントロール上の静的ラベルであっても、テキストを表示する任意の UI 要素で使用できます。 ただし、選択できない、またはカーソルがない静的テキスト コントロールでは必要ありません。
- テキストに完全にアクセスできるようにするには、 ITextProvider を 実装するコントロールでも IValueProvider インターフェイスをサポートする必要があります。 IValueProvider は、テキストを変更するプログラムによる方法を提供することで 、ITextProvider を補完します。 また、Microsoft Active Accessibility などのレガシ テクノロジに基づくものも含め、支援技術クライアント アプリケーションとの互換性も向上します。 両方のコントロール パターンが実装されている場合、 TextChanged イベント (UIA_Text_TextChangedEventId) イベントと AutomationPropertyChanged イベント (UIA_AutomationPropertyChangedEventId) は Value プロパティ (UIA_ValueValuePropertyId) と同じです。 両方のイベントがサポートされている必要があります。
- Text コントロール パターンでは、コントロールごとに 1 つのテキスト ストリームと 1 つのビューポートのみがサポートされます。 アプリケーションがペイン内のドキュメントの複数のビューを提供する場合、各ビュー (コントロール) は個別に ITextProvider を サポートする必要があります。
- ITextProvider::GetSelection メソッドは、現在選択されているテキストを表す 1 つのテキスト範囲を返す場合があります。 コントロールが複数の連続しないテキスト範囲の選択をサポートしている場合、 GetSelection メソッドは、選択したテキストのスパンごとに 1 つの ITextRangeProvider インターフェイスを含む配列を返す必要があります。
- Text コントロール パターンは、挿入ポイントを縮退 (空) のテキスト範囲として表します。 ITextProvider::GetSelection メソッドは、挿入ポイントが存在し、テキストが選択されていない場合に、縮退したテキスト範囲を返す必要があります。 詳細については、「 System Caret との相互運用性」を参照してください。
- ITextProvider::GetVisibleRanges メソッドは、連続するテキスト範囲がビューポートに表示されている場合は 1 つのテキスト範囲を返すか、または複数の部分的に表示されるテキスト行を表す結合されていないテキスト範囲の配列を返す場合があります。
- 子要素にテキストが含まれない場合、 ITextProvider::RangeFromChild メソッドは縮退範囲を返す必要があります。 埋め込みオブジェクトにはテキストを含めることができるため、 RangeFromChild メソッドは常に縮退したテキスト範囲を返すとは限りません。 詳細については、「埋め込みオブジェクトUI オートメーション公開する方法」を参照してください。
- ITextProvider::RangeFromPoint メソッドは、指定した画面座標を使用してドキュメント領域でヒット テストを実行します。 結果のテキスト範囲は、指定した画面座標の位置をクリックした結果として生じる挿入ポイントまたは選択範囲と一致している必要があります。 たとえば、指定した画面座標に画像が存在する場合、結果のテキスト範囲は、画像に対して ITextProvider::RangeFromChild メソッドが取得するテキスト範囲と同じである必要があります。 同様に、クライアント アプリケーションがシステム キャレットの中心 (挿入ポイント) の場所のテキスト範囲を要求する場合、結果のテキスト範囲はシステム キャレットの場所と同じである必要があります。
- ITextProvider::D ocumentRange プロパティは、対応する ITextProvider 実装でサポートされているすべてのテキストを含むテキスト範囲を常に提供する必要があります。
- UIA_Text_TextChangedEventIdイベントは、変更がビューポートに表示されていない場合でも、テキストの変更が発生した後に発生する必要があります。 たとえば、ユーザーが選択したテキストにまったく同じテキストを貼り付けた場合でも、プロバイダーは イベントを発生させる必要があります。
- UIA_Text_TextSelectionChangedEventIdは、テキストの選択が変更されるたびに、またはカーソル (キャレット) がテキスト間を移動するたびに発生する必要があります。
TextRange コントロール パターンを実装する場合は、次のガイドラインと規則に注意してください。
- TextRange コントロール パターンのすべてのメソッドは、テキストの表示状態に関係なく、テキスト操作を実行する必要があります。 テキスト範囲の可視性は、 IsHidden テキスト属性 (UIA_IsHiddenAttributeId) に対してクエリを実行することで常に決定できます。
- 可能であれば、プロバイダーは、削除、挿入、移動などのテキストの変更が、関連付けられているテキスト範囲オブジェクト ( ITextRangeProvider インターフェイスのインスタンス) に反映されるようにし、 UIA_Text_TextChangedEventId イベントを発生させる必要があります。 クライアントは、 イベントをヒントとして使用して、コントロールのテキストに対する編集上の変更を確認できます。
- ITextRangeProvider::Compare、CompareEndpoints、および MoveEndpointByRange メソッドで使用されるすべてのテキスト範囲オブジェクトは、同じ Text コントロール パターン実装のピアである必要があります。
- 必須ではありませんが、ITextRangeProvider::CompareEndpoints メソッドによって取得される pRetVal 値は、2 つのエンドポイント間の距離を文字 (TextUnit_Character) で示すことができます。 ただし、クライアント アプリケーションは、正または負の値を超える pRetVal の精度に依存しないようにする必要があります。
- ITextRangeProvider::ExpandToEnclosingUnit、Move、MoveEndpointByUnit の各メソッドでは、指定したテキスト単位を慎重に考慮する必要があります。 詳細については、「テキスト単位による TextRange の操作」を参照してください。
- ITextRangeProvider::Select、AddToSelection、および RemoveFromSelection メソッドに関連する実装要件については、「テキスト範囲のテキストを選択する」を参照してください。
- ITextRangeProvider::FindText メソッドと FindAttribute メソッドは、一致する 1 つのテキスト文字列またはテキスト属性を前方または後方に検索します。 一致するものが見つからない場合は NULL を 返す必要があります。
- ITextRangeProvider::GetAttributeValue メソッドは、関連付けられた属性が範囲内で変化する場合、または属性がテキスト コントロールでサポートされていない場合は、UiaGetReservedMixedAttributeValue または UiaGetReservedNotSupportedValue 関数から取得したアドレスを返す必要があります。 TextRange コントロール パターンの仕様では、新しいテキスト属性識別子を追加したり、既存の属性の定義方法を変更したりすることはできません。
- 可能であれば、 ITextRangeProvider::GetBoundingRectangles メソッドは、テキスト範囲内のテキストの完全または部分的に表示される行ごとに 1 つの外接する四角形を含む配列を返す必要があります。 これが不可能な場合、プロバイダーは、完全に表示される行のみの外接する四角形を含む配列を返すことができます。ただし、これにより、画面上でのテキストの表示方法を正確に記述するクライアント アプリケーションの機能が制限されます。
- ITextRangeProvider::GetChildren メソッドは、テキスト範囲に埋め込まれているすべての子要素を返す必要がありますが、子要素の子を返す必要はありません。 たとえば、テキスト範囲に多数の子セルを含むテーブルが含まれている場合、 GetChildren メソッドはセル要素ではなく table 要素のみを返すことができます。 パフォーマンスやアーキテクチャ上の理由から、プロバイダーは、オートメーション ツリー内のドキュメントでホストされているすべての埋め込みオブジェクトを公開できない場合があります。 この場合、プロバイダーは少なくとも GetChildren メソッドを使用した子オブジェクトの列挙をサポートし、オプションとして仮想化解除のサポートのための VirtualizedItem コントロール パターンをサポートする必要があります。
- ITextRangeProvider::GetEnclosingElement メソッドは、通常、テキスト範囲を提供するテキスト プロバイダーを返します。 ただし、テキスト プロバイダーがテーブルやハイパーリンクなどの子オブジェクトをサポートしている場合、外側の要素はテキスト プロバイダーの子孫である可能性があります。 GetEnclosingElement によって返される要素は、指定されたテキスト範囲に最も近い要素である必要があります。 たとえば、テキスト範囲がテーブルのセルにある場合、 GetEnclosingElement は table 要素ではなく、含まれているセルを返す必要があります。
- ITextRangeProvider::GetText メソッドは、範囲内のプレーン テキストを返す必要があります。 詳細については、「テキスト範囲からテキストを取得する」を参照してください。
- ITextRangeProvider::ScrollIntoView を呼び出すと、alignToTop パラメーターで指定されたテキスト コントロールのビューポート内のテキストが配置されます。 水平方向の配置に関する要件はありませんが、テキスト範囲は水平方向と垂直方向の両方で表示する必要があります。 alignToTop パラメーターを評価する場合、プロバイダーはテキスト コントロールの向きとテキストのフロー方向を考慮する必要があります。 たとえば、右から左に流れるテキストを含む垂直方向のテキスト コントロールに 対して alignToTop が TRUE の 場合、プロバイダーはテキスト範囲をビューポートの右側に揃える必要があります。
- TextUnit_Lineで文書内を移動する場合、テキスト範囲が埋め込みテーブルに入った場合、セル内のテキストの各行は行として扱われる必要があります。
ITextProvider に必要なメンバー
ITextProvider インターフェイスを実装するには、次のプロパティとメソッドが必要です。
必須メンバー | メンバーの型 | メモ |
---|---|---|
DocumentRange | プロパティ | なし |
SupportedTextSelection | プロパティ | なし |
GetSelection | 方法 | なし |
GetVisibleRanges | 方法 | なし |
RangeFromChild | 方法 | なし |
RangeFromPoint | 方法 | なし |
UIA_Text_TextChangedEventId | イベント | なし |
UIA_Text_TextSelectionChangedEventId | イベント | なし |
ITextProvider2 インターフェイスを実装するには、次の追加のプロパティとメソッドが必要です。
必須メンバー | メンバーの型 | メモ |
---|---|---|
GetCaretRange | 方法 | なし |
RangeFromAnnotation | 方法 | なし |
ITextRangeProvider の必須メンバー
ITextRangeProvider インターフェイスを実装するには、次のプロパティとメソッドが必要です。
必須メンバー | メンバーの型 | メモ |
---|---|---|
AddToSelection | 方法 | なし |
クローン | 方法 | なし |
比較 | 方法 | なし |
CompareEndpoints | 方法 | なし |
ExpandToEnclosingUnit | 方法 | なし |
FindAttribute | 方法 | なし |
Findtext | 方法 | なし |
GetAttributeValue | 方法 | なし |
GetBoundingRectangles | 方法 | なし |
GetChildren | 方法 | なし |
GetEnclosingElement | 方法 | なし |
Gettext | 方法 | なし |
[詳細ビュー] | 方法 | なし |
MoveEndpointByUnit | 方法 | なし |
MoveEndpointByRange | 方法 | なし |
選択 | 方法 | なし |
ScrollIntoView | 方法 | なし |
ITextRangeProvider2 インターフェイスを実装するには、次の追加のプロパティとメソッドが必要です。
必須メンバー | メンバーの型 | メモ |
---|---|---|
ShowContextMenu | メソッド | 「ShowContextMenu の実装」セクションを参照してください |
TextRange コントロール パターンには、関連付けられたイベントはありません。
テキスト範囲のサポート
このセクションでは、TextRange コントロール パターンをサポートするために、プロバイダーが ITextRangeProvider および ITextRangeProvider2 インターフェイスのさまざまなメソッドを実装する方法について説明します。
テキスト単位によるテキスト範囲の操作
ITextRangeProvider インターフェイスには、テキスト ベースのコントロール内のテキスト範囲を操作および移動するためのメソッドがいくつか用意されています。 ITextRangeProvider::Move、MoveEndpointByUnit、ExpandToEnclosingUnit メソッドは、文字、単語、段落など、指定したテキスト単位でテキスト範囲またはそのエンドポイントの 1 つを移動します。 詳細については、「テキスト単位のUI オートメーション」を参照してください。
その名前にもかかわらず、 ITextRangeProvider::ExpandToEnclosingUnit メソッドは必ずしもテキスト範囲を展開するとは限りません。 代わりに、エンドポイントを移動してテキスト範囲を "正規化" し、指定したテキスト単位が範囲に含まれるようにします。 指定した単位より小さい場合は範囲が拡張され、指定した単位より長い場合は短縮されます。 ExpandToEnclosingUnit メソッドは常に一貫した方法でテキスト範囲を正規化することが重要です。それ以外の場合、テキスト単位によるテキスト範囲操作の他の側面は予測できません。 次の図は、 ExpandToEnclosingUnit が 範囲のエンドポイントを移動してテキスト範囲を正規化する方法を示しています。
テキスト範囲がテキスト単位の先頭から始まり、次のテキストユニット境界の先頭または前で終わる場合、終了エンドポイントは次のテキスト単位の境界に移動されます (前の図の 1 と 2 を参照)。
テキスト範囲がテキスト単位の先頭から始まり、次の単位境界以降で終了する場合、終了エンドポイントは開始エンドポイントの後の次の単位境界に留まるか、後方に移動します (前の図の 3 と 4 を参照)。 開始エンドポイントと終了エンドポイントの間に複数のテキスト単位境界がある場合、終了エンドポイントは開始エンドポイントの後の次の単位境界に後方に移動され、テキスト範囲の長さが 1 つのテキスト単位になります。
テキスト範囲がテキスト単位の中央から始まる場合、開始エンドポイントはテキストユニットの先頭に後方に移動し、終了エンドポイントは必要に応じて開始エンドポイントの後の次の単位境界に前後に移動します (前の図の 5 から 8 を参照)。
ITextRangeProvider::Move メソッドが呼び出されると、プロバイダーは ExpandToEnclosingUnit メソッドと同じ正規化ロジックを使用して、指定したテキスト単位でテキスト範囲を正規化します。 次に、プロバイダーは、指定した数のテキスト単位で範囲を後方または前方に移動します。 範囲を移動する場合、プロバイダーはテキスト内の埋め込みオブジェクトの境界を無視する必要があります。 (ただし、単位境界自体は、埋め込みオブジェクトの存在によって影響を受ける可能性があります)。 次の図は、 Move メソッドを使用して、埋め込みオブジェクトとテキスト単位の境界を越えてテキスト範囲を単位単位で移動する方法を示しています。
次の図に示すように、 ITextRangeProvider::MoveEndpointByUnit メソッドは、指定したテキスト単位でエンドポイントの 1 つを前後に移動します。
ITextRangeProvider::MoveEndpointByRange メソッドを使用すると、クライアント アプリケーションはテキスト範囲の 1 つのエンドポイントを、2 番目のテキスト範囲の指定したエンドポイントと同じ場所に設定できます。
テキスト範囲内のテキストの選択
ITextRangeProvider インターフェイスには、テキスト ベースのコントロール内のテキストの選択を制御するためのいくつかのメソッドが含まれています。
ITextRangeProvider::Select メソッドは、テキスト範囲に対応するテキストを選択し、テキスト コントロールから前の選択範囲 (ある場合) を削除する必要があります。 生成されていないテキスト範囲で Select が呼び出された場合、プロバイダーはテキストを選択せずにテキスト範囲の場所にカーソルを移動する必要があります。
コントロールが複数の非結合のテキスト範囲の選択をサポートしている場合、 ITextRangeProvider::AddToSelection メソッドと RemoveFromSelection メソッドは、選択したテキスト範囲のコレクションにテキスト範囲を追加して削除します。 コントロールで一度に 1 つの選択したテキスト範囲のみがサポートされているが、選択操作によって複数の非結合テキスト範囲が選択される場合、プロバイダーは E_INVALIDOPERATION エラーを返すか、現在の選択範囲を拡張または切り捨てる必要があります。 ITextProvider::SupportedTextSelection プロパティは、コントロールがテキストの 1 つまたは複数の範囲の選択をサポートしているか、まったくサポートしていないかを示す必要があります。
テキスト ベースのコントロールでテキストの挿入がサポートされている場合は、コントロール内の縮退したテキスト範囲で ITextRangeProvider::AddToSelection または RemoveFromSelection を呼び出すと、挿入ポイントが移動されますが、テキストは選択されません。
テキスト範囲からテキストを取得する
ITextRangeProvider::GetText メソッドは、テキスト範囲のプレーン テキストを返す必要があります。 プレーン テキストには、キャリッジ リターンや Unicode の左から右のマーク (LRM) など、ソース テキストに含まれるすべての制御文字を含める必要があります。 プレーン テキストには、ソース テキストに存在する可能性がある HTML などのマークアップ タグを含めないようにする必要があります。 また、ソース テキスト内のすべてのエスケープ コードは、プレーン テキストに相当するものに変換する必要があります。 たとえば、" " は単純なスペース文字に変換する必要があります。
埋め込みオブジェクトがテキストの範囲にまたがる場合、プレーン テキストにはオブジェクトの内部テキストを含める必要がありますが、説明的な内部テキストと矛盾する可能性があるため、代替テキスト (埋め込みオブジェクトの name プロパティ) は含めないようにする必要があります。 詳細については、「埋め込みオブジェクトUI オートメーション公開する方法」を参照してください。
ShowContextMenu の実装
ITextRangeProvider2::ShowContextMenu は、常に範囲の始点にコンテキスト メニューを表示する必要があります。 これは、ユーザーがコンテキスト メニュー キーまたは Shift + F10 キーを押し、範囲の先頭にカーソルを置いた場合の動作と同じになります。
通常、コンテキスト メニューを表示すると、挿入ポイントが特定の場所に移動する場合は、プログラムによって ShowContextMenu を呼び出して、UI オートメーションサポートも行う必要があります。
システム キャレットとの相互運用性
挿入ポイントを正しくサポートすることは、UI オートメーションに基づいていないアプリケーションを含む多くのクライアント アプリケーションにとって重要です。 Text コントロール パターンでは、挿入ポイントは、システム キャレットの位置にある縮退した (空の) テキスト範囲で表されます。 カーソルが移動すると、コントロールは TextSelectionChanged イベント (UIA_Text_TextSelectionChangedEventId) を発生させる必要があります。 一部のクライアント アプリケーションでは、挿入ポイントの位置を監視し、テキストの選択を追跡するために、このイベントに依存しています。
コントロールに選択したテキストが含まれている場合、 現在の Text コントロール パターンのデザインでは、カーソルの位置を特定のテキスト範囲に直接関連付ける方法は提供されません。 プロバイダーは、テキストの選択を追跡し、挿入ポイントの場所を適切に設定する必要があります。 テキストの選択は通常、Shift キーまたは Ctrl キーを押しながらカーソルを移動することによって行われるため、プロバイダーは、選択が変更されるたびにこれらのキーの状態を確認することで、テキストの選択を追跡できます。
アクセシビリティ フレームワークはシステム キャレットの組み込みサポートを提供しますが、カスタム キャレットのサポートは提供しないため、テキスト ベースのコントロールでは可能な限りシステム キャレットを使用する必要があります。 カスタム キャレットを使用するコントロールでは、カスタム キャレットと同じディメンションを持つシステム キャレットを作成し、カスタム キャレットとコントロールの UI 内の同じ場所 (つまり、挿入ポイント) にシステム キャレットを配置することで、キャレットにアクセスできるようにします。 別の方法として、カスタム キャレットを使用するコントロールでは、カスタム キャレットのアクセシビリティ情報を直接提供するために 、OBJID_CARET 用の Microsoft Active Accessibility プロバイダーを実装できます。
システム キャレットの詳細については、「 キャレット」を参照してください。
コントロールがシステム キャレットの場所を適切に公開するかどうかをテストするには、 Inspect および Accessible Event Watcher ツールを使用します。
システム キャレット ビットマップの中心の画面座標は、常に挿入ポイントの位置と一致する必要があります。 そうすることで、クライアントは ITextProvider::RangeFromPoint の呼び出しでキャレット画面座標を使用して、挿入ポイントの位置を正確に表すテキスト範囲を取得できます。
関連トピック