Como usar Automação da Interface do Usuário para tornar um controle ActiveX sem janelas acessível

Descreve como usar a API do Microsoft Automação da Interface do Usuário para garantir que o controle Microsoft ActiveX sem janelas esteja acessível a aplicativos cliente at (tecnologia adaptativa).

O que você precisa saber

Tecnologias

Pré-requisitos

  • C/C++
  • Programação do Microsoft Win32 e do COM (Component Object Model)
  • Controles ActiveX sem janelas
  • provedores de Automação da Interface do Usuário

Instruções

Etapa 1: implementar as interfaces do provedor de Automação da Interface do Usuário.

Para tornar seu aplicativo acessível, você deve implementar as interfaces do provedor Automação da Interface do Usuário para o controle ActiveX sem janelas, incluindo IRawElementProviderSimple, IRawElementProviderFragment, IRawElementProviderFragmentRoot e IRawElementProviderAdviseEvents. Você deve implementar essas interfaces da mesma forma que faria para um controle baseado em janela, exceto conforme descrito nas etapas a seguir. Para obter mais informações sobre como implementar interfaces de provedor UIA, consulte Guia do programador do provedor de Automação da Interface do Usuário.

Etapa 2: implementar a interface IServiceProvider.

Quando um cliente precisa de informações de acessibilidade sobre o controle sem janelas, o contêiner de controle chama o método IServiceProvider::QueryService do controle para recuperar o ponteiro da interface IRawElementProviderSimple para o controle.

O exemplo a seguir mostra como implementar o método 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;  
}

Etapa 3: implementar o método IRawElementProviderFragment::Navigate.

Quando o método IRawElementProviderFragment::Navigate do controle sem janelas é chamado para navegar até o pai ou um irmão do provedor raiz do controle sem janelas, seu método Navigate deve delegar ao método IRawElementProviderWindowlessSite::GetAdjacentFragment do contêiner de controle.

O exemplo a seguir mostra como implementar o método 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;   
}

Etapa 4: implementar o método IRawElementProviderFragment::GetRuntimeId.

Quando o controle sem janelas recebe uma chamada para o método IRawElementProviderFragment::GetRuntimeId , o controle deve fazer o seguinte:

  1. Recupere um prefixo de ID de runtime chamando o método IRawElementProviderWindowlessSite::GetRuntimeIdPrefix do site de controle.
  2. Crie uma ID de runtime exclusiva para o controle acrescentando um inteiro ao prefixo da ID do runtime.
  3. Retornar a ID de runtime para o chamador.

O exemplo a seguir mostra como implementar o método 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;  
}

Usar MSAA para tornar um controle ActiveX sem janelas acessível

Acessibilidade de controle ActiveX sem janelas