Compartir a través de


Cómo usar Automatización de la interfaz de usuario para hacer que un control ActiveX sin ventana sea accesible

Describe cómo usar la API de Microsoft Automatización de la interfaz de usuario para asegurarse de que el control Microsoft ActiveX sin ventana es accesible para las aplicaciones cliente de tecnología de asistencia (AT).

Lo que necesita saber

Tecnologías

Requisitos previos

  • C/C++
  • Programación de Microsoft Win32 y Component Object Model (COM)
  • Controles ActiveX sin ventana
  • proveedores de Automatización de la interfaz de usuario

Instrucciones

Paso 1: Implementar las interfaces del proveedor de Automatización de la interfaz de usuario.

Para que la aplicación sea accesible, debe implementar las interfaces de proveedor de Automatización de la interfaz de usuario para el control ActiveX sin ventanas, incluido IRawElementProviderSimple, IRawElementProviderFragment, IRawElementProviderFragmentRoot e IRawElementProviderAdviseEvents. Debe implementar estas interfaces como lo haría para un control basado en ventanas, excepto como se describe en los pasos siguientes. Para obtener más información sobre cómo implementar interfaces de proveedor UIA, consulte Automatización de la interfaz de usuario Guía del programador del proveedor.

Paso 2: Implementar la interfaz IServiceProvider.

Cuando un cliente necesita información de accesibilidad sobre el control sin ventanas, el contenedor de controles llama al método IServiceProvider::QueryService del control para recuperar el puntero de interfaz IRawElementProviderSimple del control.

En el ejemplo siguiente se muestra cómo implementar el 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;  
}

Paso 3: Implemente el método IRawElementProviderFragment::Navigate.

Cuando se llama al método IRawElementProviderFragment::Navigate del control sin ventanas para navegar al elemento primario o al mismo nivel del proveedor raíz del control sin ventanas, el método Navigate debe delegar en el método IRawElementProviderWindowlessSite::GetAdjacentFragment del contenedor de controles.

En el ejemplo siguiente se muestra cómo implementar el 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;   
}

Paso 4: Implemente el método IRawElementProviderFragment::GetRuntimeId.

Cuando el control sin ventana recibe una llamada a su método IRawElementProviderFragment::GetRuntimeId , el control debe hacer lo siguiente:

  1. Recupere un prefijo de identificador de tiempo de ejecución llamando al método IRawElementProviderWindowlessSite::GetRuntimeIdPrefix del sitio de control.
  2. Cree un identificador de tiempo de ejecución único para el control anexando un entero al prefijo de identificador de tiempo de ejecución.
  3. Devuelve el identificador de tiempo de ejecución al autor de la llamada.

En el ejemplo siguiente se muestra cómo implementar el 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 hacer que un control ActiveX sin ventana sea accesible

Accesibilidad del control ActiveX sin ventanas