動的注釈の代替
UI 要素に対してカスタマイズされた IAccessible サポートを提供する方法は他にもあります。場合によっては、正しいソリューションです。 動的注釈より前は、開発者が使用できる唯一のオプションは、これらの代替手法でした。 これには、すべての IAccessible インターフェイスとプログラムによる手法の実装が含まれます。
すべての IAccessible インターフェイスの実装
もう 1 つの方法は、すべての IAccessible インターフェイスを実装することです。 このアプローチは、多くの場合、カスタム コントロールまたは根本的に異なる UI 要素に必要です。ただし、開発とテストのコストは、本当に必要でない限り避けるべきほど重要です。 1 つのプロパティを変更することが目標の場合、コストを正当化するのは困難です。
プログラムの手法
もう 1 つのオプションは、サブクラス化とラップの手法を使用して、特定のプロパティに対して公開される情報を変更することです。 これは、動的注釈を置き換えることを目的とした手法です。 サブクラス化とラップを使用して 1 つのプロパティをオーバーライドするには、開発者は次の手順を実行する必要があります。
- IAccessible オブジェクトの HWND をサブクラス化します。
- 正しい IParam/OBJID 値の WM_GETOBJECT メッセージをインターセプトします。
- CallWndProc コールバック関数を使用して、WM_GETOBJECT メッセージを基底クラスに転送します。 0 が返された場合は、 CreateStdAccessibleObject を呼び出します。それ以外の場合は、戻り値で LresultFromObject を呼び出して、コントロールのネイティブ IAccessible インターフェイス ポインターを取得します。
- ラッパー クラスを作成します。このクラスは IAccessible を実装し、前の手順から返された IAccessible インターフェイス ポインターをラップします。 このラッパー クラスは、オーバーライドされるメソッドとプロパティを除き、すべてのメソッドとプロパティを元の IAccessible インターフェイス ポインターに送信します。 これには、実際にオーバーライドされる数に関係なく、 すべての IAccessible インターフェイスの 21 個のプロパティとメソッドの転送コードを記述する必要があります。
また、開発者は次の条件を確認する必要があります。
- オーバーライドされたメソッドまたはプロパティは、必要な子 ID のみを処理し、それ以外はすべて元の IAccessible インターフェイス ポインターに転送する必要があります。
- また、元のオブジェクトでサポートされている場合にのみ、 IEnumVARIANT インターフェイスと IOleWindow インターフェイスを折り返す必要があります。
- 参照カウントは、他のインターフェイスがサポートされている場合は特に正しく処理する必要があります。
- IDispatch の戻り値は、特に ITypeInfo::Invoke メソッドで正しく処理する必要があります。これは、元の IAccessible インターフェイスへのポインターではなく、ラッパー インターフェイスへのインターフェイス ポインターを使用して呼び出す必要があります。
これらの手法では、1 つまたは 2 つのプロパティのみをオーバーライドする必要がある場合でも、かなりの作業が必要です。 結果のコードの大部分はサブクラス化とラップに関係しており、実際にオーバーライドされた情報を提供するのはごく一部だけです。
ただし、これらの手法が必要なシナリオがあります。 たとえば、プレースホルダー UI 要素を作成するために構造的な変更を行う場合は、動的注釈ではなく、これらの手法を使用する必要があります。
ラベルから派生した名前の修正
編集ボックス コントロールなど、一部の Microsoft Win32 共通コントロールは、ラベル (リソース ファイル内の LTEXT エントリ) またはグループ ボックス (リソース ファイル内の GROUPBOX) でほぼ常に使用されます。 Microsoft Active Accessibility は、コントロールの name プロパティをラベルから自動的に派生させます。 このようなコントロールの場合、ウィンドウ テキスト (名前または ID プロパティとして Microsoft Visual Studio に表示) は無視されます。通常は自動生成され、非常にわかりやすいものはほとんどありません。たとえば、"IDC_EDIT1" などです。
アプリケーションのユーザー インターフェイスが正しく設計されていない場合、Microsoft Active Accessibility で名前を正しく設定できない可能性があります。 コントロールに関連付けるためには、ラベルまたはグループ ボックスをタブ オーダーの動的コントロールの直前に配置する必要があります。
タブ オーダーは、Visual Studio のツール (リソース エディターが開いているときに [書式 ] メニュー) を使用するか、リソース ファイルを直接編集することによって変更できます。
次の例は、2 つのラベル付き編集ボックスを含むダイアログ ボックスのリソース ファイルの説明を示しています。
IDD_INPUTNAME DIALOGEX 22, 17, 312, 118
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "Enter your name"
FONT 8, "System", 0, 0, 0x0
BEGIN
DEFPUSHBUTTON "OK",IDOK,179,35,30,11,WS_GROUP
LTEXT "First Name:",IDC_STATIC,8,16,43,8
LTEXT "Last Name:",IDC_STATIC,8,33,43,8
EDITTEXT IDC_EDITFIRSTNAME,53,15,120,12,ES_AUTOHSCROLL
EDITTEXT IDC_EDITLASTNAME,53,34,120,12,ES_AUTOHSCROLL
END
この例では、ラベルとコントロールが正しいタブ オーダーに表示されません。 その結果、Microsoft Active Accessibility は名の編集ボックスに "姓" という名前を割り当て、姓の編集ボックスには名前をまったく割り当てなくなります。
次の例は、正しいリソース一覧を示しています。 また、ラベルにはショートカット キーが指定されていることにも注意してください。
IDD_INPUTNAME DIALOGEX 22, 17, 312, 118
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "Enter your name"
FONT 8, "System", 0, 0, 0x0
BEGIN
LTEXT "&First Name:",IDC_STATIC,8,16,43,8
EDITTEXT IDC_EDITFIRSTNAME,53,15,120,12,ES_AUTOHSCROLL
LTEXT "&Last Name:",IDC_STATIC,8,33,43,8
EDITTEXT IDC_EDITLASTNAME,53,34,120,12,ES_AUTOHSCROLL
DEFPUSHBUTTON "OK",IDOK,179,35,30,11,WS_GROUP
END
トラックバーの最小値や最大値などの補助ラベルがある場合、これらのラベルはタブ オーダーのコントロールの後に配置する必要があります。 コントロールのメイン ラベルは、コントロール自体の直前に表示する必要があります。
ラベルのない名前付けコントロール
すべてのコントロールに対して表示ラベルを持つことが常に可能または望ましいとは限りません。 ただし、非表示のラベルを追加することで、コントロールの名前を指定することもできます。 常に、非表示ラベルはタブ オーダーのコントロールの直前に置く必要があります。
Microsoft Visual Studio .NET でリソース エディターを使用している場合は、Visible プロパティを False に設定できます。 リソース ファイル (.rc) を編集するときにラベルを非表示にするには、次の例に示すように、not WS_VISIBLEまたはラベル コントロールのスタイル部分にを追加します。
LTEXT "&FullName:",IDC_STATIC,111,23,44,8,NOT WS_VISIBLE
ラベルが非表示の場合でも、指定されたショートカット キーは機能します。