Partager via


Comment utiliser UI Automation pour rendre un contrôle ActiveX sans fenêtre accessible

Décrit comment utiliser l’API Microsoft UI Automation pour vous assurer que votre contrôle Microsoft ActiveX sans fenêtre est accessible aux applications clientes de technologie d’assistance (AT).

Bon à savoir

Technologies

Prérequis

  • C/C++
  • Microsoft Win32 et programmation COM (Component Object Model)
  • Contrôles ActiveX sans fenêtre
  • fournisseurs UI Automation

Instructions

Étape 1 : Implémenter les interfaces de fournisseur UI Automation.

Pour rendre votre application accessible, vous devez implémenter les interfaces de fournisseur UI Automation pour votre contrôle ActiveX sans fenêtre, notamment IRawElementProviderSimple, IRawElementProviderFragment, IRawElementProviderFragmentRoot et IRawElementProviderAdviseEvents. Vous devez implémenter ces interfaces comme vous le feriez pour un contrôle basé sur une fenêtre, sauf comme décrit dans les étapes suivantes. Pour plus d’informations sur l’implémentation d’interfaces de fournisseur UIA, consultez UI Automation Guide du programmeur du fournisseur.

Étape 2 : Implémenter l’interface IServiceProvider.

Lorsqu’un client a besoin d’informations d’accessibilité sur votre contrôle sans fenêtre, le conteneur de contrôle appelle la méthode IServiceProvider::QueryService de votre contrôle pour récupérer le pointeur d’interface IRawElementProviderSimple pour votre contrôle.

L’exemple suivant montre comment implémenter la méthode 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;  
}

Étape 3 : Implémentez la méthode IRawElementProviderFragment::Navigate.

Lorsque la méthode IRawElementProviderFragment::Navigate de votre contrôle sans fenêtre est appelée pour accéder au parent ou à un frère du fournisseur racine du contrôle sans fenêtre, votre méthode Navigate doit déléguer à la méthode IRawElementProviderWindowlessSite::GetAdjacentFragment du conteneur de contrôle.

L’exemple suivant montre comment implémenter la méthode 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;   
}

Étape 4 : Implémenter la méthode IRawElementProviderFragment::GetRuntimeId.

Lorsque votre contrôle sans fenêtre reçoit un appel à sa méthode IRawElementProviderFragment::GetRuntimeId , le contrôle doit effectuer les opérations suivantes :

  1. Récupérez un préfixe d’ID d’exécution en appelant la méthode IRawElementProviderWindowlessSite::GetRuntimeIdPrefix du site de contrôle.
  2. Créez un ID d’exécution unique pour le contrôle en ajoutant un entier au préfixe d’ID d’exécution.
  3. Retourne l’ID d’exécution à l’appelant.

L’exemple suivant montre comment implémenter la méthode 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;  
}

Utiliser MSAA pour rendre un contrôle ActiveX sans fenêtre accessible

Accessibilité du contrôle ActiveX sans fenêtre