UI 자동화 사용하여 창 없는 ActiveX 컨트롤에 액세스할 수 있도록 하는 방법
Microsoft UI 자동화 API를 사용하여 창이 없는 Microsoft ActiveX 컨트롤이 AT(보조 기술) 클라이언트 애플리케이션에 액세스할 수 있도록 하는 방법을 설명합니다.
알아야 하는 작업
기술
필수 구성 요소
- C/C++
- Microsoft Win32 및 COM(구성 요소 개체 모델) 프로그래밍
- 창 없는 ActiveX 컨트롤
- UI 자동화 공급자
지침
1단계: UI 자동화 공급자 인터페이스를 구현합니다.
애플리케이션에 액세스할 수 있도록 하려면 IRawElementProviderSimple, IRawElementProviderFragment, IRawElementProviderFragmentRoot 및 IRawElementProviderAdviseEvents를 포함하여 창이 없는 ActiveX 컨트롤에 대한 UI 자동화 공급자 인터페이스를 구현해야 합니다. 다음 단계에 설명된 경우를 제외하고 창 기반 컨트롤과 마찬가지로 이러한 인터페이스를 구현해야 합니다. 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;
}
관련 항목