UI オートメーションを使用してウィンドウレス ActiveX コントロールをアクセシビリティ対応にする方法
Microsoft UI オートメーション API を使用して、ウィンドウレスの Microsoft ActiveX コントロールに支援技術 (AT) クライアント アプリケーションから確実にアクセスできるようにする方法について説明します。
知っておくべきこと
テクノロジ
前提条件
- C/C++
- Microsoft Win32 およびコンポーネント オブジェクト モデル (COM) プログラミング
- ウィンドウレス ActiveX コントロール
- UI オートメーション プロバイダー
Instructions
手順 1: UI オートメーション プロバイダー インターフェイスを実装する。
アプリケーションにアクセスできるようにするには、ウィンドウレス ActiveX コントロールのUI オートメーション プロバイダー インターフェイス (IRawElementProviderSimple、IRawElementProviderFragment、IRawElementProviderFragmentRoot、IRawElementProviderAdviseEvents など) を実装する必要があります。 これらのインターフェイスは、次の手順で説明する場合を除き、ウィンドウ ベースのコントロールの場合と同様に実装する必要があります。 UIA プロバイダー インターフェイスの実装の詳細については、「UI オートメーション プロバイダー プログラマ ガイド」を参照してください。
手順 2: IServiceProvider インターフェイスを実装する。
クライアントがウィンドウレス コントロールに関するアクセシビリティ情報を必要とする場合、コントロール コンテナーはコントロールの IServiceProvider::QueryService メソッドを呼び出して、コントロールの IRawElementProviderSimple インターフェイス ポインターを取得します。
次の例は、 QueryService メソッドを実装する方法を示しています。
STDMETHODIMP CMyAccessibleUIAControl::QueryService(REFGUID guidService,
REFIID riid, void **ppvObject)
{
if (ppvObject == NULL)
{
return E_INVALIDARG;
}
*ppvObject = NULL;
HRESULT hr = E_FAIL;
if (guidService == __uuidof(IRawElementProviderSimple))
{
hr = QueryInterface(riid, ppvObject);
}
return hr;
}
手順 3: IRawElementProviderFragment::Navigate メソッドを実装する。
ウィンドウレス コントロールの IRawElementProviderFragment::Navigate メソッドを呼び出して、ウィンドウレス コントロールのルート プロバイダーの親または兄弟に移動すると、 Navigate メソッドはコントロール コンテナーの IRawElementProviderWindowlessSite::GetAdjacentFragment メソッドに委任する必要があります。
次の例は、 Navigate メソッドを実装する方法を示しています。
STDMETHODIMP CMyAccessibleUIAControl::Navigate(NavigateDirection direction,
IRawElementProviderFragment **ppRetVal)
{
if (ppRetVal == NULL)
{
return E_INVALIDARG;
}
*ppRetVal = NULL;
HRESULT hr = E_FAIL;
IRawElementProviderWindowlessSite *pWindowlessSite = NULL;
if (direction == NavigateDirection_Parent)
{
// Query the control container's windowless site
// for the parent.
if (SUCCEEDED(m_pClientSite->QueryInterface(
IID_PPV_ARGS(&pWindowlessSite))))
{
hr = pWindowlessSite->GetAdjacentFragment(direction, ppRetVal);
}
}
else if (direction == NavigateDirection_FirstChild)
{
// GetFragmentForChild is an application-defined function that
// retrieves the first or last child fragment.
hr = GetFragmentForChild(FIRST, ppRetVal);
}
else if (direction == NavigateDirection_LastChild)
{
hr = GetFragmentForChild(LAST, ppRetVal);
}
SafeRelease(&pWindowlessSite);
return S_OK;
}
手順 4: IRawElementProviderFragment::GetRuntimeId メソッドを実装します。
ウィンドウレス コントロールが IRawElementProviderFragment::GetRuntimeId メソッドの呼び出しを受け取った場合、コントロールは次の操作を行う必要があります。
- コントロール サイトの IRawElementProviderWindowlessSite::GetRuntimeIdPrefix メソッドを呼び出して、ランタイム ID プレフィックスを取得します。
- ランタイム ID プレフィックスに整数を追加して、コントロールの一意のランタイム ID を作成します。
- ランタイム ID を呼び出し元に返します。
次の例は、 GetRuntimeId メソッドを実装する方法を示しています。
STDMETHODIMP CMyAccessibleUIAControl::GetRuntimeId(SAFEARRAY **ppRetVal)
{
if (ppRetVal == NULL)
{
return E_INVALIDARG;
}
*ppRetVal = NULL;
HRESULT hr = E_FAIL;
IRawElementProviderWindowlessSite *pWindowlessSite = NULL;
if (SUCCEEDED(m_pClientSite->QueryInterface(IID_PPV_ARGS(&pWindowlessSite))))
{
// Create a safe array to hold runtime ID.
SAFEARRAY *psa = SafeArrayCreateVector(VT_I4, 1, 3);
if (psa == NULL)
{
hr = E_OUTOFMEMORY;
}
// Retrieve the runtime ID prefix from the control container. The prefix
// consists of UiaAppendRuntimeId followed by the windowless site ID.
if (SUCCEEDED(hr))
{
hr = pWindowlessSite->GetRuntimeIdPrefix(&psa);
}
if (SUCCEEDED(hr))
{
// Append this fragment's ID to the retrieved runtime ID prefix.
long i = 2;
hr = SafeArrayPutElement(psa, &i, (void*)&m_Id);
}
if (SUCCEEDED(hr))
{
*ppRetVal = psa;
}
}
SafeRelease(&pWindowlessSite);
return hr;
}
関連トピック