다음을 통해 공유


공급자용 IAccessibleEx 구현

이 섹션에서는 IAccessibleEx 인터페이스를 구현하여 Microsoft UI 자동화 공급자 기능을 Microsoft Active Accessibility 서버에 추가하는 방법을 설명합니다.

IAccessibleEx구현하기 전에 다음 요구 사항을 고려합니다.

  • 기준 Microsoft Active Accessibility 액세스 가능 개체 계층 구조는 클린 합니다. IAccessibleEx 는 기존 액세스 가능한 개체 계층의 문제를 해결할 수 없습니다. IAccessibleEx를 구현하기 전에 Microsoft Active Accessibility 구현에서 개체 모델 구조의 문제를 수정해야 합니다.
  • IAccessibleEx 구현은 Microsoft Active Accessibility 사양과 UI 자동화 사양을 모두 준수해야 합니다. 도구는 두 사양에 따라 규정 준수의 유효성을 검사하는 데 사용할 수 있습니다. 자세한 내용은 접근성 테스트 및 UI 자동화 확인(UIA 확인) 테스트 자동화 프레임워크를 참조하세요.

IAccessibleEx구현하려면 다음 기본 단계가 필요합니다.

  • IAccessibleEx 인터페이스를 이 개체 또는 별도의 개체에서 찾을 수 있도록 액세스 가능한 개체에 IServiceProvider를 구현합니다.
  • 액세스 가능한 개체에서 IAccessibleEx를 구현합니다.
  • Microsoft Active Accessibility 자식 항목에 액세스할 수 있는 개체를 만듭니다. 이 개체는 Microsoft Active Accessibility에서 부모 개체의 IAccessible 인터페이스로 표시됩니다(예: 목록 항목). 이러한 개체에서 IAccessibleEx를 구현합니다.
  • 액세스 가능한 모든 개체에 대해 IRawElementProviderSimple을 구현합니다.
  • 액세스 가능한 개체에 적절한 컨트롤 패턴 인터페이스를 구현합니다.

IServiceProvider 인터페이스 구현

컨트롤에 대한 IAccessibleEx 구현은 별도의 개체에 있을 수 있으므로 클라이언트 애플리케이션은 QueryInterface를 사용하여 이 인터페이스를 가져올 수 없습니다. 대신 클라이언트는 IServiceProvider::QueryService를 호출해야 합니다. 이 메서드의 다음 예제 구현에서는 IAccessibleEx가 별도의 개체에 구현되지 않은 것으로 가정하므로 이 메서드는 단순히 QueryInterface통해 호출합니다.

           
HRESULT CListboxAccessibleObject::QueryService(REFGUID guidService, REFIID riid, LPVOID *ppvObject)
{
    if (ppvObject == NULL)
    {
        return E_INVALIDARG;
    }
    *ppvObject = NULL;
    if (guidService == __uuidof(IAccessibleEx))
    {
        return QueryInterface(riid, ppvObject);
    }
    else 
    {
        return E_NOINTERFACE;
    }
};      

IAccessibleEx 인터페이스 구현

Microsoft Active Accessibility에서 UI 요소는 항상 IAccessible 인터페이스 및 자식 ID로 식별됩니다. IAccessible단일 인스턴스는 여러 UI 요소를 나타낼 수 있습니다.

IAccessibleEx 인스턴스는 단일 UI 요소만 나타내므로 각 IAccessible 및 자식 ID 쌍은 단일 IAccessibleEx 인스턴스에 매핑되어야 합니다. IAccessibleEx 에는 이 매핑을 처리하는 두 가지 메서드가 포함되어 있습니다.

  • GetObjectForChild - 지정된 자식에 대한 IAccessibleEx 인터페이스를 검색합니다. IAccessibleEx 구현에서 지정된 자식 ID를 인식하지 못하거나, 지정된 자식에 대한 IAccessibleEx가 없거나, 자식 요소를 나타내는 경우 이 메서드는 NULL을 반환합니다.
  • GetIAccessiblePair - IAccessibleEx 요소에 대한 IAccessible 인터페이스 및 자식 ID를 검색합니다. 자식 ID를 사용하지 않는 IAccessible 구현의 경우 이 메서드는 해당 IAccessible 개체를 검색하고 CHILDID_SELF.

다음 예제에서는 사용자 지정 목록 보기의 항목에 대한 GetObjectForChildGetIAccessiblePair 메서드의 구현을 보여 줍니다. 이 메서드를 사용하면 UI 자동화 IAccessible 및 자식 ID 쌍을 해당 IAccessibleEx 인스턴스에 매핑할 수 있습니다.

           
HRESULT CListboxAccessibleObject::GetObjectForChild(
    long idChild, IAccessibleEx **ppRetVal)
{ 
    VARIANT vChild;
    vChild.vt = VT_I4;
    vChild.lVal = idChild;
    HRESULT hr = ValidateChildId(vChild);
    if (FAILED(hr))
    {
        return E_INVALIDARG;
    }
    // List item accessible objects are stored as an array of
    // pointers; for the purpose of this example it is assumed that 
    // the list contents will not change. Accessible objects are
    // created only when needed.
    if (itemProviders[idChild - 1] == NULL)
    {
        // Create an object that supports UI Automation and
        // IAccessibleEx for the item.
        itemProviders[idChild - 1] = 
          new CListItemAccessibleObject(idChild, 
          g_pListboxControl);
        if (itemProviders[idChild - 1] == NULL)
        {
            return E_OUTOFMEMORY;
        }
    }
    IAccessibleEx* pAccEx = static_cast<IAccessibleEx*>
      (itemProviders[idChild - 1]);
    if (pAccEx != NULL)
    {
      pAccEx->AddRef();
    }
    *ppRetVal = pAccEx;
    return S_OK; 
}

HRESULT CListItemAccessibleObject::GetIAccessiblePair(
    IAccessible **ppAcc, long *pidChild)
{ 
    if (ppAcc == NULL || pidChild == NULL)
    {
        return E_INVALIDARG;   
    }

                CListboxAccessibleObject* pParent = 
        m_control->GetAccessibleObject();

    HRESULT hr = pParent->QueryInterface( 
        __uuidof(IAccessible), (void**)ppAcc);
    if (FAILED(hr))
    {
        *pidChild = 0;
        return E_NOINTERFACE;
    }
    *pidChild = m_childID; 
    return S_OK; 
}
}

액세스 가능한 개체 구현에서 자식 ID를 사용하지 않는 경우 다음 코드 조각과 같이 메서드를 계속 구현할 수 있습니다.

           

    // This sample implements IAccessibleEx on the same object; it could use a tear-off
    // or inner object instead.
    class MyAccessibleImpl: public IAccessible,
                        public IAccessibleEx,
                        public IRawElementProviderSimple
    {
    public:
    ...
   HRESULT STDMETHODCALLTYPE GetObjectForChild( long idChild, IAccessibleEx **ppRetVal )
    {
        // This implementation does not support child IDs.
        *ppRetVal = NULL;
        return S_OK;
    }

    HRESULT STDMETHODCALLTYPE GetIAccessiblePair( IAccessible ** ppAcc, long * pidChild )
    {
        // This implementation assumes that IAccessibleEx is implemented on same object as
        // IAccessible.
        *ppAcc = static_cast<IAccessible *>(this);
        (*ppAcc)->AddRef();
        *pidChild = CHILDID_SELF;
        return S_OK;
    }

IRawElementProviderSimple 인터페이스 구현

서버는 IRawElementProviderSimple을 사용하여 UI 자동화 속성 및 컨트롤 패턴에 대한 정보를 노출합니다. IRawElementProviderSimple 에는 다음 메서드가 포함됩니다.

  • GetPatternProvider - 이 메서드는 컨트롤 패턴 인터페이스를 노출하는 데 사용됩니다. 지정된 컨트롤 패턴을 지원하는 개체를 반환하거나 , 컨트롤 패턴이 지원되지 않는 경우 NULL 을 반환합니다.
  • GetPropertyValue - 이 메서드는 UI 자동화 속성 값을 노출하는 데 사용됩니다.
  • HostRawElementProvider - 이 메서드는 IAccessibleEx 구현과 함께 사용되지 않습니다.
  • ProviderOptions - 이 메서드는 IAccessibleEx 구현과 함께 사용되지 않습니다.

IAccessibleEx 서버는 IRawElementProviderSimple::GetPatternProvider를 구현하여 컨트롤 패턴을 노출합니다. 이 메서드는 컨트롤 패턴을 지정하는 정수 매개 변수를 사용합니다. 패턴이 지원되지 않는 경우 서버는 NULL을 반환합니다. 컨트롤 패턴 인터페이스가 지원되는 경우 서버는 IUnknown 반환하고 클라이언트는 QueryInterface를 호출하여 적절한 컨트롤 패턴을 가져옵니다.

IAccessibleEx 서버는 IRawElementProviderSimple::GetPropertyValue구현하고 속성을 매개 변수로 식별하는 정수 PROPERTYID를 제공하여 UI 자동화 속성(예: LabeledBy 및 IsRequiredForForm)을 지원할 수 있습니다. 이 기술은 컨트롤 패턴 인터페이스에 포함되지 않은 UI 자동화 속성에만 적용됩니다. 컨트롤 패턴 인터페이스와 연결된 속성은 컨트롤 패턴 인터페이스 메서드를 통해 노출됩니다. 예를 들어 SelectionItem 컨트롤 패턴의 IsSelected 속성은 ISelectionItemProvider::get_IsSelected 노출됩니다.