共用方式為


如何使用 消費者介面自動化 讓無視窗 ActiveX 控制項可供存取

描述如何使用 Microsoft 消費者介面自動化 API,確保您的無視窗 Microsoft ActiveX 控制項可供輔助技術 (AT) 用戶端應用程式存取。

您所需了解的事情

技術

必要條件

  • C/C++
  • Microsoft Win32 和元件物件模型 (COM) 程式設計
  • 無視窗 ActiveX 控制項
  • 消費者介面自動化提供者

指示

步驟 1:實作消費者介面自動化提供者介面。

若要讓應用程式可供存取,您必須實作無視窗 ActiveX 控制項的消費者介面自動化提供者介面,包括IRawElementProviderSimpleIRawElementProviderFragmentIRawElementProviderFragmentRootIRawElementProviderAdviseEvents。 您應該像針對視窗型控制項一樣實作這些介面,但下列步驟中所述除外。 如需實作 UIA 提供者介面的詳細資訊,請參閱消費者介面自動化提供者程式設計人員指南

步驟 2:實作 IServiceProvider 介面。

當用戶端需要無視窗控制項的協助工具資訊時,控制項容器會呼叫控制項的 IServiceProvider::QueryService 方法,以擷取控制項的 IRawElementProviderSimple 介面指標。

下列範例示範如何實作 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;  
}

步驟 3:實作 IRawElementProviderFragment::Navigate 方法。

當無視窗控制項的 IRawElementProviderFragment::Navigate 方法被呼叫以巡覽至無視窗控制項根提供者的父系或同層級時, Navigate 方法應該委派給控制項容器的 IRawElementProviderWindowlessSite::GetAdjacentFragment 方法。

下列範例示範如何實作 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;   
}

步驟 4:實作 IRawElementProviderFragment::GetRuntimeId 方法。

當無視窗控制項收到其 IRawElementProviderFragment::GetRuntimeId 方法的呼叫時,控制項必須執行下列動作:

  1. 呼叫控制項網站的 IRawElementProviderWindowlessSite::GetRuntimeIdPrefix 方法,以擷取執行時間識別碼前置詞。
  2. 將整數附加至執行時間識別碼前置詞,為控制項建立唯一的執行時間識別碼。
  3. 將執行時間識別碼傳回給呼叫端。

下列範例示範如何實作 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;  
}

使用 MSAA 讓無視窗 ActiveX 控制項可供存取

無視窗 ActiveX 控制項協助工具