Korzystanie z funkcji IAccessibleEx z klienta
W tym temacie wyjaśniono, jak klienci uzyskują dostęp do implementacji serwera IAccessibleEx i używają go do uzyskiwania właściwości automatyzacji interfejsu użytkownika i wzorców kontroli dla elementów interfejsu użytkownika.
W procedurach i przykładach w tej sekcji założono, że klient IAccessible jest już w trakcie przetwarzania oraz istnieje istniejący serwer Microsoft Active Accessibility. Zakładają również, że klient uzyskał już obiekt IAccessible przy użyciu jednej z funkcji struktury ułatwień dostępu, takich jak AccessibleObjectFromEvent, AccessibleObjectFromPointlub AccessibleObjectFromWindow.
Uzyskiwanie interfejsu IAccessibleEx z interfejsu IAccessible
Klient, który ma interfejs IAccessible dla dostępnego obiektu, może go użyć do uzyskania odpowiedniego interfejsu IAccessibleEx, wykonując następujące kroki:
- Wywołaj QueryInterface na oryginalnym obiekcie IAccessible z identyfikatorem IID __uuidof(IServiceProvider).
- Wywołaj IServiceProvider::QueryService, aby uzyskać IAccessibleEx.
Obsługa identyfikatora dziecka
Klienci muszą być przygotowani dla serwerów o identyfikatorze podrzędnym innym niż CHILDID_SELF. Po uzyskaniu interfejsu IAccessibleEx z IAccessibleklienci muszą wywołać IAccessibleEx::GetObjectForChild, jeśli identyfikator podrzędny nie jest CHILDID_SELF (wskazujący obiekt nadrzędny).
W poniższym przykładzie pokazano, jak uzyskać IAccessibleEx dla określonego obiektu IAccessible i identyfikatora podrzędnego.
HRESULT GetIAccessibleExFromIAccessible(IAccessible * pAcc, long idChild,
IAccessibleEx ** ppaex)
{
*ppaex = NULL;
// First, get IServiceProvider from the IAccessible.
IServiceProvider * pSp = NULL;
HRESULT hr = pAcc->QueryInterface(IID_IServiceProvider, (void **) & pSp);
if(FAILED(hr))
return hr;
if(pSp == NULL)
return E_NOINTERFACE;
// Next, get the IAccessibleEx for the parent object.
IAccessibleEx * paex = NULL;
hr = pSp->QueryService(__uuidof(IAccessibleEx), __uuidof(IAccessibleEx),
(void **)&paex);
pSp->Release();
if(FAILED(hr))
return hr;
if(paex == NULL)
return E_NOINTERFACE;
// If this is for CHILDID_SELF, we're done. Otherwise, we have a child ID and
// can request the object for child.
if(idChild == CHILDID_SELF)
{
*ppaex = paex;
return S_OK;
}
else
{
// Get the IAccessibleEx for the specified child.
IAccessibleEx * paexChild = NULL;
hr = paex->GetObjectForChild(idChild, &paexChild);
paex->Release();
if(FAILED(hr))
return hr;
if(paexChild == NULL)
return E_NOINTERFACE;
*ppaex = paexChild;
return S_OK;
}
}
Uzyskiwanie interfejsu IRawElementProviderSimple
Jeśli klient ma interfejs IAccessibleEx, może użyć interfejsu QueryInterface, aby przejść do interfejsu IRawElementProviderSimple, jak pokazano w poniższym przykładzie.
HRESULT GetIRawElementProviderFromIAccessible(IAccessible * pAcc, long idChild,
IRawElementProviderSimple ** ppEl)
{
* ppEl = NULL;
// First, get the IAccessibleEx for the IAccessible and child ID pair.
IAccessibleEx * paex;
HRESULT hr = GetIAccessibleExFromIAccessible( pAcc, idChild, &paex );
if(FAILED(hr))
return hr;
// Next, use QueryInterface.
hr = paex->QueryInterface(__uuidof(IRawElementProviderSimple), (void **)ppEl);
paex->Release();
return hr;
}
Pobieranie wzorców sterowania
Jeśli klient ma dostęp do interfejsu IRawElementProviderSimple, może pobrać interfejsy wzorca sterowania zaimplementowane przez dostawców, a następnie wywołać metody w tych interfejsach. W poniższym przykładzie pokazano, jak to zrobić.
// Helper function to get a pattern interface from an IAccessible and child ID
// pair. Gets the IAccessibleEx, then calls GetPatternObject and QueryInterface.
HRESULT GetPatternFromIAccessible(IAccessible * pAcc, long idChild,
PATTERNID patternId, REFIID iid, void ** ppv)
{
// First, get the IAccesibleEx for this IAccessible and child ID pair.
IRawElementProviderSimple * pel;
HRESULT hr = GetIRawElementProviderSimpleFromIAccessible(pAcc, idChild, &pel);
if(FAILED(hr))
return hr;
if(pel == NULL)
return E_NOINTERFACE;
// Now get the pattern object.
IUnknown * pPatternObject = NULL;
hr = pel->GetPatternProvider(patternId, &pPatternObject);
pel->Release();
if(FAILED(hr))
return hr;
if(pPatternObject == NULL)
return E_NOINTERFACE;
// Finally, use QueryInterface to get the correct interface type.
hr = pPatternObject->QueryInterface(iid, ppv);
pPatternObject->Release();
if(*ppv == NULL)
return E_NOINTERFACE;
return hr;
}
HRESULT CallInvokePatternMethod(IAccessible * pAcc, long idChild)
{
IInvokeProvider * pPattern;
HRESULT hr = GetPatternFromIAccessible(pAcc, varChild,
UIA_InvokePatternId, __uuidof(IInvokeProvider),
(void **)&pPattern);
if(FAILED(hr))
return hr;
hr = pPattern->Invoke();
pPattern->Release();
return hr;
}
Pobieranie wartości właściwości
Jeśli klient ma dostęp do IRawElementProviderSimple, może pobrać wartości właściwości. W poniższym przykładzie pokazano, jak uzyskać wartości właściwości AutomationId i LabeledBy Microsoft UI Automation.
#include <initguid.h>
#include <uiautomationcoreapi.h> // Includes the UI Automation property GUID definitions.
#include <uiautomationcoreids.h> // Includes definitions of pattern/property IDs.
// Assume we already have a IRawElementProviderSimple * pEl.
VARIANT varValue;
// Get AutomationId property:
varValue.vt = VT_EMPTY;
HRESULT hr = pEl->GetPropertyValue(UIA_AutomationIdPropertyId, &varValue);
if(SUCCEEDED(hr))
{
if(varValue.vt == VT_BSTR)
{
// AutomationId is varValue.bstrVal.
}
VariantClear(&varValue);
}
// Get LabeledBy property:
varValue.vt = VT_EMPTY;
hr = pEl->GetPropertyValue(UIA_LabeledByPropertyId, &varValue);
if(SUCCEEDED(hr))
{
if(varValue.vt == VT_UNKNOWN || varValue.punkVal != NULL)
{
// Use QueryInterface to get IRawElementProviderSimple.
IRawElementProviderSimple * pElLabel = NULL;
hr = varValue.punkVal->QueryInterface(__uuidof(IRawElementProviderSimple),
(void**)& pElLabel);
if (SUCCEEDED(hr))
{
if(pElLabel != NULL)
{
// Use the pElLabel pointer here.
pElLabel ->Release();
}
}
}
VariantClear(&varValue);
}
Powyższy przykład dotyczy właściwości, które nie są skojarzone ze wzorcem kontrolki. Aby uzyskać właściwości wzorca kontroli dostępu, klient musi uzyskać i użyć interfejsu wzorca sterowania.
Pobieranie interfejsu IAccessible z interfejsu IRawElementProviderSimple
Jeśli klient uzyska interfejs IRawElementProviderSimple dla elementu interfejsu użytkownika, może go wykorzystać do uzyskania odpowiedniego interfejsu IAccessible dla tego elementu. Jest to przydatne, jeśli klient musi uzyskać dostęp do właściwości Microsoft Active Accessibility dla elementu.
Klient może uzyskać interfejs IRawElementProviderSimple jako wartość właściwości (na przykład wywołując IRawElementProviderSimple::GetPropertyValue za pomocą UIA_LabeledByPropertyId) lub jako element pobrany metodą (na przykład wywołując ISelectionProvider::GetSelection, aby pobrać tablicę IRawElementProviderSimple interfejsów wybranych elementów). Po uzyskaniu interfejsu IRawElementProviderSimple klient może go użyć do uzyskania odpowiedniego IAccessible, wykonując następujące kroki:
- Spróbuj użyć QueryInterface, aby uzyskać interfejs IAccessibleEx.
- Jeśli QueryInterface nie powiedzie się, wywołaj IAccessibleEx::ConvertReturnedElement na instancji IAccessibleEx, z której pierwotnie uzyskano właściwość.
- Wywołaj metodę GetIAccessiblePair w nowym wystąpieniu IAccessibleEx, aby uzyskać IAccessible interfejs i identyfikator elementu podrzędnego.
Poniższy fragment kodu ilustruje, jak uzyskać interfejs IAccessible z wcześniej uzyskanego interfejsu IRawElementProviderSimple.
// IRawElementProviderSimple * pVal - an element returned by a property or method
// from another IRawElementProviderSimple.
IAccessible * pAcc = NULL;
long idChild;
// First, try to use QueryInterface to get the IAccessibleEx interface.
IAccessibleEx * pAccEx;
HRESULT hr = pVal->QueryInterface(__uuidof(IAccessibleEx), (void**)&pAccEx);
if (SUCCEEDED(hr)
{
if (!pAccEx)
{
// If QueryInterface fails, and the IRawElementProviderSimple was
// obtained as a property or return value from another
// IRawElementProviderSimple, pass it to the
// IAccessibleEx::ConvertReturnedValue method of the
// originating element.
pAccExOrig->ConvertReturnedElement(pVal, &pAccEx);
}
if (pAccEx)
{
// Call GetIAccessiblePair to get an IAccessible interface and
// child ID.
pAccEx->GetIAccessiblePair(&pAcc, &idChild);
}
// Finally, use the IAccessible interface and child ID.
if (pAcc)
{
// Use IAccessible methods to get further information about this UI
// element, or pass it to existing code that works in terms of
// IAccessible.
...
}
}