Sdílet prostřednictvím


Implementace zprostředkovatele automatizace uživatelského rozhraní Server-Side

Toto téma popisuje, jak implementovat zprostředkovatele Microsoft UI Automation na straně serveru pro vlastní ovládací prvek napsaný v jazyce C++. Obsahuje následující části:

Příklady kódu, které ukazují, jak implementovat zprostředkovatele na straně serveru, najdete v tématu How-To Témata pro zprostředkovatele automatizace uživatelského rozhraní.

Struktura stromu zprostředkovatele

Pro každý prvek uživatelského rozhraní, který musí být přístupný pro klienta UIA, musíte implementovat zprostředkovatele UIA.

Například každý prvek musí implementovat IRawElementProviderFragment zatímco kořenový prvek aplikace musí implementovat IRawElementProviderFragmentRoot. Kromě toho by každý prvek zprostředkovatele měl odkazovat na:

  • rodič
  • předchozí prvek poskytovatele
  • prvek dalšího poskytovatele
  • první podřízený zprostředkovatel
  • poslední podřízený zprostředkovatel

Rozhraní poskytovatele

Následující rozhraní modelu COM (Component Object Model) poskytují funkce pro vlastní ovládací prvky. Aby bylo možné poskytovat základní funkce, musí každý poskytovatel automatizace uživatelského rozhraní implementovat alespoň IRawElementProviderSimple rozhraní. Rozhraní IRawElementProviderFragment a IRawElementProviderFragmentRoot jsou volitelná, ale měla by být implementována pro prvky v komplexním ovládacím prvku, aby poskytovala další funkcionalitu.

Rozhraní Popis
IRawElementProviderSimple Poskytuje základní funkce pro ovládací prvek hostovaný v okně, včetně podpory vzorů ovládacích prvků a vlastností.
IRawElementProviderFragment Přidává funkčnost pro prvek v komplexním ovládacím prvku, včetně navigace ve fragmentu, nastavení fokusu a vrácení ohraničujícího obdélníku prvku.
IRawElementProviderFragmentRoot Přidá funkce pro kořenový prvek v komplexním ovládacím prvku, včetně vyhledání podřízeného prvku na zadaných souřadnicích a nastavení stavu fokusu pro celý ovládací prvek.

 

Poznámka

V rozhraní API pro automatizaci uživatelského rozhraní pro spravovaný kód tvoří tato rozhraní hierarchii dědičnosti. Nejedná se o případ v jazyce C++, kde jsou rozhraní zcela oddělená.

 

Následující rozhraní poskytují přidané funkce, ale implementace je volitelná.

Rozhraní Popis
IRawElementProviderAdviseEvents Umožňuje poskytovateli sledovat požadavky na události.
IRawElementProviderHwndOverride Umožňuje přemístit prvky založené na okně ve stromu automatizace uživatelského rozhraní fragmentu.

 

Požadované funkce pro zprostředkovatele automatizace uživatelského rozhraní

Abyste mohli komunikovat s automatizací uživatelského rozhraní, musí váš ovládací prvek implementovat hlavní oblasti funkcí popsané v následující tabulce.

Funkčnost Implementace
Zpřístupnění zprostředkovatele pro automatizaci uživatelského rozhraní V reakci na WM_GETOBJECT zprávu poslanou do ovládacího okna vraťte objekt, který implementuje IRawElementProviderSimple. V případě fragmentů to musí být zprostředkovatel kořene fragmentu.
Zadejte hodnoty vlastností. Implementujte IRawElementProviderSimple::GetPropertyValue pro zadání nebo přepsání hodnot.
Povolte klientovi interakci s ovládacím prvkem. Implementujte rozhraní, která podporují každý vhodný řídicí vzor, například IInvokeProvider. V implementaci IRawElementProviderSimple::GetPatternProvidervraťte tyto zprostředkovatele vzorů ovládacích prvků.
Vyvolání událostí UiaRaiseAutomationEvent, metody IProxyProviderWinEventSink.
Povolte navigaci a zaměření v fragmentu. Implementujte IRawElementProviderFragment pro každý prvek v rámci fragmentu. Není nutné pro prvky, které nejsou součástí fragmentu.
Umožnění zaměření a nalezení podřízených prvků uvnitř fragmentu. Implementujte IRawElementProviderFragmentRoot. Není nutné pro prvky, které nejsou kořeny fragmentů.

 

Hodnoty vlastností

Poskytovatelé automatizace uživatelského rozhraní pro vlastní ovládací prvky musí podporovat určité vlastnosti, které můžou používat automatizace uživatelského rozhraní a klientské aplikace. U prvků hostovaných ve Windows může automatizace uživatelského rozhraní načíst některé vlastnosti z výchozího zprostředkovatele okna, ale musí získat jiné od vlastního zprostředkovatele.

Poskytovatelé ovládacích prvků založených na okně obvykle nemusí poskytovat následující vlastnosti, které jsou identifikované PROPERTYID:

Vlastnost RuntimeId jednoduchého elementu nebo kořene fragmentu hostovaného v okně se získá z okna. Prvky fragmentu pod kořenem, například položky seznamu v rámci seznamového pole, však musí obsahovat vlastní identifikátory. Další informace naleznete v tématu IRawElementProviderFragment::GetRuntimeId.

Vlastnost IsKeyboardFocusable by měla být vrácena pro zprostředkovatele hostované v ovládacím prvku Windows Forms. V tomto případě nemusí být výchozí zprostředkovatel okna schopen načíst správnou hodnotu.

Vlastnost Name je obvykle poskytována poskytovatelem hostitele.

Události od poskytovatelů

Poskytovatelé automatizace uživatelského rozhraní by měli vyvolat události, aby klientské aplikace informovaly o změnách ve stavu uživatelského rozhraní. K vyvolání událostí se používají následující funkce.

Funkce Popis
UiaRaiseAutomationEvent Vyvolává různé události, včetně událostí aktivovaných kontrolními vzory.
UiaRaiseAutomationPropertyChangedEvent Vyvolá událost při změně vlastnosti Automatizace uživatelského rozhraní.
UiaRaiseStructureChangedEvent Vyvolá událost, když se změní struktura stromu Automatizace uživatelského rozhraní, například odebráním nebo přidáním prvku.

 

Účelem události je informovat klienta o něčem, co probíhá v uživatelském rozhraní. Zprostředkovatelé by měli vyvolat událost bez ohledu na to, jestli byla změna aktivována uživatelským vstupem nebo klientskou aplikací pomocí automatizace uživatelského rozhraní. Například událost identifikovaná UIA_Invoke_InvokedEventId by měla být vyvolána při každém vyvolání ovládacího prvku, a to buď prostřednictvím přímého vstupu uživatele, nebo klientské aplikace volající IUIAutomationInvokePattern::Invoke.

Aby bylo možné optimalizovat výkon, může poskytovatel selektivně vyvolat události nebo vyvolat vůbec žádné události, pokud není zaregistrovaná žádná klientská aplikace k jejich přijetí. Pro optimalizaci se používají následující prvky rozhraní API.

API prvek Popis
UiaClientsAreListening Tato funkce zjišťuje, jestli se některé klientské aplikace přihlásily k odběru událostí automatizace uživatelského rozhraní.
IRawElementProviderAdviseEvents Implementace tohoto rozhraní na kořenu fragmentu umožňuje poskytovateli být informován, když klienti zaregistrují a zruší registraci obslužných rutin pro události na fragmentu.

 

Poznámka

Podobně jako implementace počítání referencí v programování modelu COM, je důležité, aby poskytovatelé automatizace uživatelského rozhraní zacházeli s metodami IRawElementProviderAdviseEvents::AdviseEventAdded a AdviseEventRemoved stejně jako s metodami IUnknown::AddRef a Release rozhraní IUnknown. Pokud bylo AdviseEventAdded voláno vícekrát než AdviseEventRemoved pro konkrétní událost nebo vlastnost, poskytovatel by měl pokračovat ve vyvolávání odpovídajících událostí, protože někteří klienti stále naslouchají. Případně můžou poskytovatelé automatizace uživatelského rozhraní použít funkci UiaClientsAreListening určit, jestli alespoň jeden klient naslouchá, a pokud ano, vyvolat všechny příslušné události.

 

Navigace zprostředkovatele

Poskytovatelé jednoduchých ovládacích prvků, jako je vlastní tlačítko hostované v okně, nemusí podporovat navigaci ve stromu Automatizace uživatelského rozhraní. Navigace do elementu a z tohoto prvku je zpracována výchozím zprostředkovatelem pro okno hostitele, který je zadán v implementaci IRawElementProviderSimple::HostRawElementProvider. Při implementaci zprostředkovatele pro komplexní vlastní ovládací prvek však musíte podporovat navigaci mezi kořenovým uzlem fragmentu a jeho potomky a mezi uzly na stejné úrovni.

Poznámka

Prvky jiného fragmentu než kořenového adresáře musí vracet null z HostRawElementProvider, protože nejsou přímo hostované v okně, a žádný výchozí zprostředkovatel nemůže podporovat navigaci do a z nich.

 

Struktura fragmentu je určena vaší implementací IRawElementProviderFragment::Navigate. Pro každý možný směr z každého fragmentu vrátí tato metoda objekt zprostředkovatele pro prvek v tomto směru. Pokud neexistuje žádný prvek v daném směru, metoda vrátí NULL.

Kořen fragmentu podporuje navigaci pouze na podřízené prvky. Například ovládací prvek seznamu vrátí první položku, když je směr nastaven na NavigateDirection_FirstChild, a vrátí poslední položku, když je směr nastaven na NavigateDirection_LastChild. Kořen fragmentu nepodporuje navigaci k rodiči nebo k sourozencům; to obstarává poskytovatel okna hostitele.

Prvky fragmentu, které nejsou kořenem, musí podporovat navigaci k rodiči a ke každému sourozenci a dítěti, které mají.

Přiřazení nového rodiče

Automaticky otevíraná okna jsou ve skutečnosti okna nejvyšší úrovně a ve výchozím nastavení se ve stromu Automatizace uživatelského rozhraní zobrazují jako podřízené položky plochy. V mnoha případech jsou však automaticky otevíraná okna logicky podřízená jiným ovládacím prvkům. Například rozevírací seznam kombinačního pole je logicky podřízený kombinačnímu poli. Podobně je vyskakovací okno nabídky logicky potomkem nabídky. Automatizace uživatelského rozhraní poskytuje podporu pro přiřazení nového nadřazeného objektu k automaticky otevíranému oknu, aby se zdálo, že jde o podřízený prvek přidruženého ovládacího prvku.

Přiřazení nového nadřazeného objektu k automaticky otevíranému oknu:

  1. Vytvořte zprostředkovatele pro automaticky otevírané okno. To vyžaduje, aby třída automaticky otevíraného okna byla předem známa.
  2. Implementujte všechny vlastnosti a vzory ovládacích prvků obvyklým způsobem pro toto vyskakovací okno, jako by šlo samo o sobě o ovládací prvek.
  3. Implementujte IRawElementProviderSimple::HostRawElementProvider vlastnost tak, aby vrátila hodnotu získanou z UiaHostProviderFromHwnd, kde parametr je popisovač vyskakovacího okna.
  4. Implementujte IRawElementProviderFragment::Navigate pro vyskakovací okno a jeho nadřazený objekt, aby navigace byla správně zpracována od logického nadřazeného objektu k logickým potomkům a mezi sourozeneckými potomky.

Když automatizace uživatelského rozhraní narazí na vyskakovací okno, rozpozná, že navigace je přepsána z výchozího nastavení, a přeskočí vyskakovací okno, když se objeví jako potomek na ploše. Místo toho je uzel dostupný pouze prostřednictvím fragmentu.

Přiřazení nového nadřazeného objektu není vhodné pro případy, kdy může ovládací prvek hostovat okno jakékoli třídy. Ovládací prvek typu rebar může například hostit libovolný typ okna ve svých pásmech. Automatizace uživatelského rozhraní pro zpracování těchto případů podporuje alternativní formu přemístění oken, jak je popsáno v další části.

Přeorientování poskytovatele

Fragmenty automatizace uživatelského rozhraní mohou obsahovat dva nebo více prvků, které jsou obsaženy v okně. Protože každé okno má svého výchozího poskytovatele, který považuje okno za podřízené ve vztahu k obsahujícímu oknu, strom automatizace uživatelského rozhraní ve výchozím nastavení zobrazí okna ve fragmentu jako podřízená nadřazenému oknu. Ve většině případů je to žádoucí chování, ale někdy může vést k nejasnostem, protože neodpovídá logické struktuře uživatelského rozhraní.

Dobrým příkladem je ovládací prvek rebaru. Ovládací prvek rebar obsahuje pruhy, z nichž každý může obsahovat ovládací prvek v okně, jako je panel nástrojů, textové pole nebo rozbalovací seznam. Výchozí poskytovatel oken pro okna panelu rozpoznává okna ovládacích prvků pásu jako podřízené prvky, a poskytovatel panelu rozpoznává pásy jako podřízené prvky. Vzhledem k tomu, že poskytovatel okna a poskytovatel rebaru spolupracují a spojují své podřízené prvky, pásy a ovládací prvky závislé na okně se zobrazují jako podřízené prvky ovládacího prvku rebar. Logicky by se ale měly jako podřízené prvky ovládacího prvku rebaru zobrazovat pouze pásy a každý poskytovatel pásma by měl být svázán s výchozím poskytovatelem okna pro ovládací prvek, který obsahuje.

K tomuto účelu poskytovatel kořene fragmentu pro ovládací prvek rebar odhaluje sadu podřízených objektů, které představují pásma. Každé pásmo má jednoho poskytovatele, který může vystavit vlastnosti a kontrolní vzory. Ve své implementaci IRawElementProviderSimple::HostRawElementProvidervrátí zprostředkovatel pásma výchozího poskytovatele okna pro ovládací okno, které získá voláním UiaHostProviderFromHwnd, předáním ovládacího okna popisovače (HWND). Nakonec, zprostředkovatel kořenového fragmentu pro rebar implementuje rozhraní IRawElementProviderHwndOverride a ve své implementaci IRawElementProviderHwndOverride::GetOverrideProviderForHwndvrátí odpovídajícího poskytovatele pásma pro obsažený ovládací prvek v zadaném okně.

Odpojení zprostředkovatelů

Aplikace obvykle vytvářejí ovládací prvky podle potřeby a následně je zničí. Po zničení ovládacího prvku by měly být uvolněny prostředky zprostředkovatele automatizace uživatelského rozhraní přidružené k ovládacího prvku voláním UiaDisconnectProvider.

Podobně by aplikace měla použít funkci UiaDisconnectAllProviders k uvolnění všech prostředků automatizace uživatelského rozhraní uchovávané všemi poskytovateli v aplikaci před vypnutím.

Průvodce programátora pro zprostředkovatele automatizace uživatelského rozhraní