Compartir a través de


Adición de la funcionalidad de Automatización de la interfaz de usuario en servidores Active Accessibility

Los controles que no tienen un proveedor de Automatización de interfaz de usuario de Microsoft, pero que implementan IAccessible se pueden actualizar fácilmente para proporcionar algunas funciones de Automatización de interfaz de usuario, implementando la interfaz IAccessibleEx. Esta interfaz permite que el control exponga propiedades y patrones de control de Automatización de interfaz de usuario, sin necesidad de una implementación completa de interfaces de proveedor de Automatización de interfaz de usuario como IRawElementProviderFragment. Para implementar IAccessibleEx, la jerarquía de objetos de Microsoft Active Accessibility de referencia no debe contener errores ni incoherencias (por ejemplo, un objeto secundario cuyo objeto primario no lo enumera como secundario) y no debe entrar en conflicto con las especificaciones de Automatización de interfaz de usuario. Si la jerarquía de objetos de Microsoft Active Accessibility cumple estos requisitos, es un buen candidato para agregar funcionalidad mediante IAccessibleEx; de lo contrario, debe implementar Automatización de interfaz de usuario solo o junto con la implementación de Microsoft Active Accessibility.

Veamos el caso de un control personalizado que tenga un valor de intervalo. El servidor de Microsoft Active Accessibility para el control define su rol y puede devolver su valor actual, pero carece de los medios para devolver los valores mínimo y máximo del control, ya que estas propiedades no están definidas en Microsoft Active Accessibility. Un cliente de Automatización de interfaz de usuario puede recuperar el rol del control, el valor actual y otras propiedades de Microsoft Active Accessibility, ya que el núcleo de Automatización de interfaz de usuario puede obtenerlos a través de IAccessible. Sin embargo, sin acceso a una interfaz IRangeValueProvider en el objeto, Automatización de interfaz de usuario tampoco puede recuperar los valores máximos y mínimos.

El desarrollador de controles podría proporcionar un proveedor completo de Automatización de interfaz de usuario para el control, pero esto significaría duplicar gran parte de la funcionalidad existente de la implementación de IAccessible: por ejemplo, navegación y propiedades comunes. En su lugar, el desarrollador puede seguir confiando en IAccessible para proporcionar esta funcionalidad, al tiempo que agrega compatibilidad con propiedades específicas del control a través de IRangeValueProvider.

La actualización del control personalizado requiere estos pasos principales:

  • Implemente IServiceProvider en el objeto accesible para que la interfaz de IAccessibleEx se pueda encontrar en este o en un objeto independiente.
  • Implemente IAccessibleEx en el objeto accesible.
  • Crear objetos accesibles distintos para cualquier elemento secundario de Microsoft Active Accessibility, que en Microsoft Active Accessibility podría haberse representado mediante la interfaz IAccessible en el objeto primario (por ejemplo, elementos de lista). Implemente IAccessibleEx en estos objetos.
  • Implemente IRawElementProviderSimple en todos los objetos accesibles.
  • Implemente las interfaces de patrón de control adecuadas en los objetos accesibles.

En este tema se incluyen las siguientes secciones.

Exponer IAccessibleEx

Dado que la implementación de IAccessibleEx para un control puede residir en un objeto independiente, las aplicaciones cliente no pueden confiar en QueryInterface para obtener esta interfaz. En su lugar, se espera que los clientes llamen a IServiceProvider::QueryService. En la siguiente implementación de ejemplo de este método, se supone que IAccessibleEx no se implementa en un objeto independiente; por lo tanto, el método simplemente llama a través de QueryInterface.

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

Implementar IAccessibleEx

El método de IAccessibleEx que tiene mayor interés es GetObjectForChild. Este método ofrece al servidor de Microsoft Active Accessibility la oportunidad de crear un objeto accesible (uno que expone, como mínimo, IAccessibleEx) para un elemento secundario. En Microsoft Active Accessibility, los elementos secundarios normalmente no se representan como objetos accesibles, sino como elementos secundarios de un objeto accesible. Sin embargo, dado que Automatización de interfaz de usuario requiere que cada elemento se represente mediante un objeto accesible independiente, GetObjectForChild debe crear un objeto independiente para cada elemento secundario a petición.

La siguiente implementación de ejemplo devuelve un objeto accesible para un elemento en una vista de lista personalizada.

HRESULT CListboxAccessibleObject::GetObjectForChild(long idChild, IAccessibleEx **pRetVal)
{ 
    *pRetVal = NULL;
    VARIANT vChild;
    vChild.vt = VT_I4;
    vChild.lVal = idChild;

    // ValidateChildId is an application-defined function that checks whether
    // the child ID is valid. This is similar to code that validates the varChild
    // parameter in IAccessible methods.
    //
    // Additionally, if this idChild corresponds to a child that has its own
    // IAccessible, we should also return E_INVALIDARG here. (The caller
    // should instead be using the IAccessibleEx from that child's own
    // IAccessible in that case.)
    if (idChild == CHILDID_SELF || FAILED(ValidateChildId(vChild)))
    {
        return E_INVALIDARG;
    }

    // Return a suitable provider for this specific child.
    // This implementation returns a new instance each time; an implementation
    // can cache these if desired.

    // _pListboxControl is a member variable pointer to the owning control.
    IAccessibleEx* pAccEx  = new CListItemAccessibleObject(idChild, _pListboxControl);
    if (pAccEx == NULL)
    {
        return E_OUTOFMEMORY;
    }
    *pRetVal = pAccEx;
    return S_OK; 
}

Para obtener una implementación de ejemplo completa, vea Hacer que los controles personalizados sean accesibles, parte 5: Usar IAccessibleEx para agregar compatibilidad con Automatización de interfaz de usuario a un control personalizado.

Guía del programador del proveedor de Automatización de interfaz de usuario