IAccessibleEx インターフェイスを使用して既存の Microsoft Active Accessibility サーバーに
|
UI オートメーションのコントロール パターン | Microsoft Active Accessibility の役割 |
Invoke パターン | ROLE_SYSTEM_PUSHBUTTON ROLE_SYSTEM_MENUITEM ROLE_SYSTEM_BUTTONDROPDOWN ROLE_SYSTEM_SPLITBUTTON および accDefaultAction が NULL ではないすべての役割 |
Selection Item パターン | ROLE_SYSTEM_LISTITEM ROLE_SYSTEM_RADIOBUTTON |
Selection パターン | ROLE_SYSTEM_LIST |
Toggle パターン | ROLE_SYSTEM_CHECKBUTTON |
Value パターン | ROLE_SYSTEM_TEXT (読み取り専用ではない場合) ROLE_SYSTEM_PROGRESSBAR ROLE_SYSTEM_COMBOBOX および accValue が NULL ではないときの他のすべての役割 |
Window パターン | 最上位レベルの Win32 HWND で自動的にサポート |
ページのトップへ
c. プロパティ: Microsoft Active Accessibility と UI オートメーションとの重複
以下の UI オートメーション プロパティには、Microsoft Active Accessibility に相当するプロパティがありません。これらの UI オートメーション プロパティは IAccessibleEx 実装のものを使用することができます。
- AutomationId
- AriaProperties
- AriaRole
- ClassName
- ClickablePoint
- ControllerFor
- Culture
- DescribedBy
- FlowsTo
- FrameworkId
- IsContentElement
- IsControlElement
- IsDataValidForForm
- IsRequiredForForm
- ItemStatus
- ItemType
- LabeledBy
- LocalizedControlType
- Orientation
下表の UI オートメーション要素のプロパティは Microsoft Active Accessibility のプロパティと重複するため、以下の例外を除いて IAccessibleEx 実装のものを使用できます。
- AcceleratorKey と AccessKey: Microsoft Active Accessibility の accKeyboardShortcut プロパティと重複しますが、コントロールがアクセス キーとアクセラレータ (ショートカット キー) の両方を持つ場合には提供することができます。
- ControlType: Microsoft Active Accessibility の accRole プロパティと重複しますが、より詳細なコントロール タイプ情報を提供するように指定できます。
Microsoft Active Accessibility のプロパティが対応している、UI オートメーション要素のプロパティを下表にまとめます。これらのプロパティについては、IAccessibleEx 実装のものを使用する必要はありません。
UI オートメーションのプロパティ | Microsoft Active Accessibility のプロパティ |
Rect BoundingRectangle | accLocation |
bool HasKeyboardFocu | accState, STATE_SYSTEM_FOCUSED |
bool IsEnabled | accState, STATE_SYSTEM_UNAVAILABLE |
bool IsKeyboardFocusable | accState, STATE_SYSTEM_FOCUSABLE |
bool IsPassword | accState, STATE_SYSTEM_PROTECTED |
string HelpText | accHelp |
string Name | accName |
int NativeWindowHandle | WindowFromAccessibleObject |
bool IsOffscreen | accState, STATE_SYSTEM_INVISIBLE/OFFSCREEN |
int ProcessId | コア UIA が提供 UIA |
int [] RuntimeId | コア UIA が提供 UIA |
ページのトップへ
d. イベントおよび WM_GETOBJECT メッセージ
IAccessibleEx を使って Microsoft Active Accessibility の実装を拡張する際には、Microsoft Active Accessibility のサーバーとクライアントがイベントを処理するのと同じ方法で、イベントが発生して処理されます。
IAccessibleEx 用に定義されたイベントに加えて、IAccessibleEx の実装には、以下の UI オートメーションのイベント ID を使用できます。
UI オートメーションのイベント | Microsoft Active Accessibility のイベント |
IsEnabledPropertyChangedEvent | EVENT_OBJECT_STATECHANGE |
ItemStatusPropertyChangedEvent | 該当なし |
ExpandCollapseExpandCollapseStatePropertyChangedEvent | EVENT_OBJECT_STATECHANGE |
MultipleViewCurrentViewPropertyChangedEvent | 該当なし |
ScrollHorizontallyScrollablePropertyChangedEvent | 該当なし |
ScrollHorizontalViewSizePropertyChangedEvent | 該当なし |
ScrollVerticallyScrollablePropertyChangedEvent | 該当なし |
ScrollVerticalViewSizePropertyChangedEvent | 該当なし |
ToggleToggleStatePropertyChangedEvent | EVENT_OBJECT_STATECHANGE |
ScrollHorizontalScrollPercentPropertyChangedEvent | EVENT_OBJECT_CONTENTSCROLLED |
ScrollVerticalScrollPercentPropertyChangedEvent | EVENT_OBJECT_CONTENTSCROLLED |
MSAA EVENT_OBJECT_<value> が関連付けられたイベントの場合、IAccessibleEx 実装では表中の UI オートメーション イベントに加えて、この関連付けられたイベントも発生させる必要があります。これによって IAccessible クライアントはイベントを受け取ることができますが、詳細情報を他のクライアントと通信することにもなります。
ページのトップへ
4. 実装のサンプル シナリオ
IAccessibleEx の実装と使用には難しい作業が必要になることも確かです。そこで、アプリケーション開発者とアクセシビリティ クライアント向けのサンプル シナリオを以下に 2 つ紹介します。
a. シナリオ 1: Microsoft Active Accessibility サーバーに対して IAccessibleEx インターフェイスを使用し UI オートメーションを実装する
最初のシナリオでは、IAccessibleEx と IRawElementProviderSimple を使用して Microsoft Active Accessibility 実装サーバーから UI オートメーション情報を公開します。
1. IServiceProvider インターフェイスを実装する
プロバイダーに対する最初の手順として、既存の IAccessible オブジェクトに IServiceProvider を実装します。サービス ID が __uuidof(IAccessibleEx) であるサービスに対する QueryService への着信呼び出しは、IAccessibleEx を実装するオブジェクトへの参照を返します。
2. ChildId を実装する
Microsoft Active Accessibility では、UI 要素が常に IAccessible COM インターフェイスと ChildId オブジェクト識別子のペアで識別されます。つまり、1 つの IAccessible COM オブジェクトが複数の UI 要素を表現できます。
1 つの IAccessibleEx インスタンスが 1 つの UI 要素を表すため、このインスタンスが IAccessible と ChildId のペアから対応する IAccessibleEx へのマッピングを行います。IAccessibleEx には、このマッピングを処理する 2 つのメソッドが含まれています。
- GetObjectForChild: 指定した子要素の IAccessibleEx 要素を返します。実装が ChildId を使用しない場合、指定した子要素に IAccessibleEx がない場合、または既に子要素が表されている場合は、S_OK または NULL を返します。
- GetIAccessiblePair: IAccessibleEx 要素の IAccessible と ChildId のペアを返します。ChildId を使用しない IAccessible 実装では、対応する IAccessible オブジェクトと CHILDID_SELF を返します。
アクセス可能なオブジェクトの実装で ChildId を使用しない場合でも、これらのメソッドは依然として下記の例のように実装することができます。
// このサンプルでは、同一オブジェクトに IAccessibleEx を実装しますが、
// ティアオフ オブジェクトや内部オブジェクトを使用することもできます。
class MyAccessibleImpl: public IAccessible,
public IAccessibleEx,
public IRawElementProviderSimple
{
public:
...
HRESULT STDMETHODCALLTYPE GetObjectForChild( long idChild, IAccessibleEx ** pRetVal )
{
// この実装では ChildID はサポートしません。
*pRetVal = NULL;
return S_OK;
}
HRESULT STDMETHODCALLTYPE GetIAccessiblePair( IAccessible ** ppAcc, long * pidChild )
{
// ここでは IAccessibleEx が IAccessible と同じオブジェクトに
// 実装されていると想定しています。
*ppAcc = static_cast<IAccessible *>(this);
(*ppAcc)->AddRef();
*pidChild = CHILDID_SELF;
return S_OK;
}</code></pre>
ページのトップへ
3. IRawElementProviderSimple インターフェイスを実装する
サーバーでは IRawElementProviderSimple を使って UI オートメーションのプロパティとコントロール パターンに関する情報を公開します。IRawElementProviderSimple には以下のメソッドがあります。
- ProviderOptions: IAccessibleEx 実装では使用されません。
- GetPatternProvider: コントロール パターン インターフェイスを公開するために使用されます。指定したコントロール パターンをサポートするオブジェクト、またはコントロール パターンがサポートされない場合は NULL 値を返します。
- GetPropertyValue: UI オートメーションのプロパティ値を公開するために使用されます。
- HostRawElementProvider: IAccessibleEx 実装では使用されません。
IAccessibleEx サーバーは、IRawElementProviderSimple::GetPatternProvider を実装することによりコントロール パターンを公開します。このメソッドはコントロール パターンを指定する整数型のパラメーターを受け取ります。パターンがサポートされない場合、サーバーは NULL を返します。コントロール パターン インターフェイスがサポートされている場合、サーバーは IUnknown を返し、続いてクライアントが QueryInterface を呼び出して適切なコントロール パターンを取得します。
IAccessibleEx サーバーは、IRawElementProviderSimple::GetPropertyValue を実装し、プロパティをパラメーターとして識別できる PROPERTYID 整数値を指定することにより、LabeledBy や IsRequiredForForm などの UI オートメーションのプロパティをサポートできます。この技法は、コントロール パターン インターフェイスに含まれない UI オートメーション プロパティにのみ適用されます。一方、コントロール パターン インターフェイスと関連付けられたプロパティは、コントロール パターン インターフェイスのメソッドを通じて公開されます。たとえば、SelectionItem コントロール パターンからの IsSelected プロパティは、ISelectionItemProvider::get_IsSelected で公開されることになります。
ChildId で表される子オブジェクトが Microsoft Active Accessibility 実装のベースラインに含まれている場合、IRawElementProviderSimple の対応する実装が IAccessible と ChildId のペア (Microsoft Active Accessibility のアクセス可能なオブジェクト) にマップされるように、IAccessibleEx を通じて両者間の差異を正確に処理してください。
UI オートメーション プロパティ、イベント、およびコントロール パターンの ID はすべて、Windows 7 SDK に付属する UIAutomation.h 内で定義されています。
ページのトップへ
b. シナリオ 2: Microsoft Active Accessibility のインプロセス クライアントに対する IAccessibleEx インターフェイス
この 2 つ目のサンプル シナリオでは、Microsoft Active Accessibility サーバーが既に存在し、IAccessible クライアントがインプロセスで実行されていると想定した場合の手順とサンプルを提供します。また、アクセシビリティ フレームワーク API の AccessibleObjectFromEvent、AccessibleObjectFromPoint、または AccessibleObjectFromWindow のいずれかを使用して IAccessible オブジェクトを既に取得している状態であるとします。
1. IAccessible インターフェイスから IAccessibleEx インターフェイスを取得する
- IID が __uuidof(IServiceProvider) となっている 元の IAccessible オブジェクトで QueryInterface を呼び出します。
- IServiceProvider::QueryService を呼び出して IAccessibleEx を取得します。
2. ChildId を処理する
クライアントでは、サーバーに対する ChildId 値を CHILDID_SELF 以外の値で準備する必要があります。クライアントは IAccessible から IAccessibleEx を取得した後、ChildId 値が CHILDID_SELF ではない (つまり親オブジェクトを示す) 場合に GetObjectForChild を呼び出す必要があります。
以下のコードに IAccessible オブジェクトと ChildId のペアに対する IAccessibleEx の取得方法を示します。
HRESULT GetIAccessibleExFromIAccessible( IAccessible * pAcc, long idChild,
IAccessibleEx ** ppaex )
{
*ppaex = NULL;
// まず、IAccessible から IServiceProvider を取得します。
IServiceProvider * pSp = NULL;
HRESULT hr = pAcc->QueryInterface( IID_IServiceProvider, (void **) & pSp );
if(FAILED(hr))
return hr;
if(pSp == NULL)
return E_NOINTERFACE;
// 次に、親オブジェクトの IAccessibleEx を取得します。
IAccessibleEx * paex = NULL;
hr = pSp->QueryService(__uuidof(IAccessibleEx), __uuidof(IAccessibleEx),
(void **)&paex);
pSp->Release();
if(FAILED(hr))
return hr;
if(paex == NULL)
return E_NOINTERFACE;
// これが CHILDID_SELF に対するものであれば、これで完了です。それ以外の場合、
// 子 ID が必要です。これをオブジェクトに要求します。
if(idChild == CHILDID_SELF)
{
*ppaex = paex;
return S_OK;
}
else
{
// 指定した idChild の IAccessibleEx を取得します。
IAccessibleEx * paexChild = NULL;
hr = paex->GetObjectForChild(idChild, &paexChild);
paex->Release();
if(FAILED(hr))
return hr;
if(paexChild == NULL)
return E_NOINTERFACE;
*ppaex = paexChild;
return S_OK;
}
}
ページのトップへ
3. IRawElementProviderSimple インターフェイスを取得する
クライアントに IAccessibleEx インターフェイスがある場合、以下の例のように QueryInterface を使用して、IRawElementProviderSimple インターフェイスを取得できます。
HRESULT GetIRawElementProviderFromIAccessible( IAccessible * pAcc, long idChild,
IRawElementProviderSimple ** ppEl )
{
* ppEl = NULL;
// まず、IAccessible/idChild のペアに対する IAccessibleEx を取得します。
IAccessibleEx * paex;
HRESULT hr = GetIAccessibleExFromIAccessible( pAcc, idChild, &paex );
if(FAILED(hr))
return hr;
// 次に、QueryInterface を使用します。
hr = paex->QueryInterface(__uuidof(IRawElementProviderSimple), (void **)ppEl);
paex->Release();
return hr;
}
ページのトップへ
4. コントロール パターンを使用する
クライアントが IRawElementProviderSimple へのアクセスを確立すると、以下の例に示すように、プロバイダーに実装されているコントロール パターンのインターフェイスを取得することができます。クライアントはこれらのインターフェイスのメソッドを呼び出すことができます。
// IAccessible/idChild のペアからパターン インターフェイスを取得するためのヘルパー。
// IAccessibleEx を取得してから、GetPatternObject と QueryInterface を呼び出します。
HRESULT GetPatternFromIAccessible( IAccessible * pAcc, long idChild,
PATTERNID patternId, REFIID iid, void ** ppv )
{
// まず、IAccessible/idChild のペアに対する IAccessibleEx を取得します。
IRawElementProviderSimple * pel;
HRESULT hr = GetIRawElementProviderSimpleFromIAccessible( pAcc, idChild, &pel );
if(FAILED(hr))
return hr;
if(paex == NULL)
return E_NOINTERFACE;
// ここでパターン オブジェクトを取得します。
IUnknown * pPatternObject = NULL;
hr = pel->GetPatternProvider(patternId, &pPatternObject);
pel->Release();
if(FAILED(hr))
return hr;
if(pPatternObject == NULL)
return E_NOINTERFACE;
// 最後に、QueryInterface によって正しいインターフェイス タイプを問い合わせます。
hr = pPatternObject->QueryInterface(iid, ppv);
pPatternObject->Release();
if(*ppv == NULL)
return E_NOINTERFACE;
return hr;
}
HRESULT CallInvokePatternMethod( IAccessible * pAcc, long idChild )
{
IInvokeProvider * pPattern;
HRESULT hr = GetPatternFromIAccessible(pAcc, varChild,
UIA_InvokePatternId, __uuidof(IInvokeProvider),
(void **)&pPattern);
if(FAILED(hr))
return hr;
hr = pPattern->Invoke();
pPattern->Release();
return hr;
}
ページのトップへ
5. プロパティ値を取得する
クライアントから IRawElementProviderSimple にアクセスできるようになったら、コントロール パターンを取得できるだけでなく、プロパティ値にもアクセスできるようになります。次のサンプル コードでは AutomationId (文字列) や LabeledBy (別の要素への参照) といった UI オートメーション プロパティの値を取得する方法を示します。
#include <initguid.h>
#include <uiautomationcoreapi.h> // UI オートメーション プロパティの GUID 定義をインクルードします。
#include <uiautomationcoreids.h> // パターンとプロパティ ID の定義をインクルードします。
// ここでは IRawElementProviderSimple * pEl: を既に取得していると想定します。
VARIANT varValue;
// AutomationId プロパティを取得します。
varValue.vt = VT_EMPTY;
HRESULT hr = pEl->GetPropertyValue(UIA_AutomationIdPropertyId, &varValue);
if(SUCCEEDED(hr))
{
if(varValue.vt == VT_BSTR)
{
// AutomationId は varValue.bstrVal です。
}
VariantClear(&varValue);
}
// LabeledBy プロパティを取得します。
varValue.vt = VT_EMPTY;
hr = pEl->GetPropertyValue(UIA_LabeledByPropertyId, &varValue);
if(SUCCEEDED(hr))
{
if(varValue.vt == VT_UNKNOWN || varValue.punkVal != NULL)
{
// QueryInterface により IRawElementProviderSimple に問い合わせを行います。
IRawElementProviderSimple * pElLabel = NULL;
hr = varValue.punkVal->QueryInterface(__uuidof(IRawElementProviderSimple),
(void**)& pElLabel);
if(pElLabel != NULL)
{
// ここで pElLabel を使用します。
pElLabel ->Release();
}
}
VariantClear(&varValue);
}
ここで紹介したサンプル コードは、コントロール パターンと関連付けられていないプロパティに適用されます。コントロール パターンのプロパティの場合は、クライアントがコントロール パターン インターフェイスへのアクセスを確立した後、そのインターフェイスでプロパティ値を要求できます。
ページのトップへ
6. IRawElementProviderSimple インターフェイスから IAccessible インターフェイスに逆変換する
UIA_LabeledByPropertyId を指定して GetPropertyValue を呼び出すか、IRawElementProviderSimple の SAFEARRAY を返す ISelectionProvider::GetSelection メソッドを使用してクライアントが IRawElementProviderSimple をプロパティ値として取得すると、IAccessible プロパティの取得を可能にする IAccessible を取得できます。この IAccessible は IRawElementProviderSimple に対応します。
- まず、IAccessibleEx に対して QueryInterface を実行します。
- QueryInterface が失敗した場合、本来プロパティが取得される IAccessibleEx インスタンスの ConvertReturnedElement を使用します。
- 次に、この新しい IAccessibleEx の GetIAccessiblePair メソッドを使用して、IAccessible と ChildId 値を取得します。
// IRawElementProviderSimple * pVal: プロパティまたはメソッドによって、
// 別の IRawElementProviderSimple から返される要素です。
IAccessible * pAcc = NULL;
long idChild;
// まず、IAccessibleEx に対して QueryInterface 実行します。
IAccessibleEx * pAccEx = pVal->QueryInterface(__uuidof(IAccessibleEx));
if(!pAccEx)
{
// QueryInterface が失敗し、IRawElementProviderSimple がプロパティまたは
// 別の IRawElementProviderSimple から返された値として取得された場合、
// その値を、取得元の要素の IAccessibleEx.ConvertReturnedValue に渡します。
pAccExOrig->ConvertReturnedElement(pVal, &pAccEx);
}
if(pAccEx)
{
// GetIAccessiblePair を呼び出して {IAccessible, idChild} を取得します。
pAccEx->GetIAccessiblePair(&pAcc, &idChild);
}
// 最後に IAccessible、idChild を使用します。
if(pAcc)
{
// この UI 要素についての詳細情報を取得するには IAccessible メソッドを使用するか、
// IAccessible の観点から問題なく機能する既存のコードに渡します。
...
}
ページのトップへ
5. まとめ
IAccessibleEx インターフェイスにより、既存の Microsoft Active Accessibility サーバーの実装に UI オートメーションのプロパティやコントロール パターンを追加できます。IAccessibleEx インターフェイスは、UI オートメーションに対する既存の Microsoft Active Accessibility サーバーの機能を強化する費用対効果の高い方法、または Microsoft Active Accessibility のインプロセス クライアントから UI オートメーション プロバイダー インターフェイスに直接アクセスするための方法を提供します。
ページのトップへ
6. 詳細情報
- UI オートメーションや Microsoft Active Accessibility など、最新の Windows Automation API 3.0 に関する詳細情報とライブラリについては、Windows 7 および .NET Framework 3.5 Service Pack 1 用 Windows® ソフトウェア開発キット (SDK) を参照してください。
- 最新の Windows Automation API 3.0 の詳細については、CoDe Focus Magazine の記事「Windows Automation API 3.0 Overview」(英語) を参照してください。この記事は、CoDe Focus Magazine (英語) で参照できます。
- 一般的なアクセシビリティ製品の開発リソースについては、マイクロソフト アクセシビリティ デベロッパー センターを参照してください。
- UI オートメーションの仕様については、「UI オートメーションの仕様と Community Promise」を参照してください。
ページのトップへ