伺服器端 UI 自動化提供者實作

注意

本文件適用對象為 .NET Framework 開發人員,其想要使用 System.Windows.Automation 命名空間中定義的受控 UI 自動化類別。 如需 UI 自動化的最新資訊,請參閱 Windows 自動化 API:UI 自動化

本節描述如何為自訂控制項實作伺服器端使用者介面自動化提供者。

Windows Presentation Foundation (WPF) 元素和非 WPF 元素 (例如針對Windows Forms 所設計的元素) 的實作基本上不同。 WPF 元素透過從 AutomationPeer 衍生的類別提供 UI 自動化支援。 非 WPF 元素透過提供者介面的實作提供支援。

安全性考量

應該寫入提供者,以便他們可在部分信任環境中運作。 因為 UIAutomationClient.dll 未設定為在部分信任下執行,所以您的提供者程式碼不應該參考該組件。 如果這樣做,程式碼可在完全信任環境中執行,但無法在部分信任環境中執行。

尤其,不要使用來自 UIAutomationClient.dll 中類別的欄位,例如 AutomationElement中的欄位。 請改用來自 UIAutomationTypes.dll 中類別的對等欄位,例如 AutomationElementIdentifiers

依 Windows Presentation Foundation 項目的提供者實作

如需本主題的詳細資訊,請參閱 WPF 自訂控制項的 UI 自動化

依非 WPF 項目的提供者實作

不屬於 WPF 架構,但以受控程式碼撰寫而成的自訂控制項 (其中大多是 Windows Forms 控制項),可藉由實作介面提供 UI 自動化支援。 每個項目必須至少實作下一節中第一個資料表列出的其中一個介面。 此外,如果項目支援一或多個控制項模式,它必須針對每個控制項模式實作適當的介面。

您的 UI 自動化提供者專案必須參考下列組件:

  • UIAutomationProviders.dll

  • UIAutomationTypes.dll

  • WindowsBase.dll

提供者介面

每個 UI 自動化提供者必須實作下列其中一個介面。

介面 描述
IRawElementProviderSimple 提供功能給裝載在視窗中的簡單控制項,包括支援控制項模式和屬性。
IRawElementProviderFragment 繼承自 IRawElementProviderSimple。 為複雜控制項中的項目新增功能,包括在片段內導覽、設定焦點,以及傳回項目的週框。
IRawElementProviderFragmentRoot 繼承自 IRawElementProviderFragment。 為複雜控制項中的根項目新增功能,包括在指定的座標尋找子項目,以及設定整個控制項的焦點狀態。

下列介面提供新增的功能,但不需要實作。

介面 描述
IRawElementProviderAdviseEvents 可讓提供者追蹤事件的要求。
IRawElementProviderHwndOverride 可讓以視窗為基礎的元素在片段的 UI 自動化樹狀結構內重新定位。

System.Windows.Automation.Provider 命名空間中的其他所有介面則是用於控制項模式支援。

非 WPF 提供者的需求

若要與 UI 自動化通訊,您的控制項必須實作下列主要功能領域:

功能 實作
將提供者公開給 UI 自動化 在回應傳送至控制項視窗的 WM_GETOBJECT 訊息時,傳回實作 IRawElementProviderSimple 的物件 (或衍生的介面)。 對於片段,這必須是片段根的提供者。
提供屬性值 實作 GetPropertyValue 來提供或覆寫值。
可讓用戶端與控制項互動 實作支援控制模式的介面,例如 IInvokeProvider。 實作 GetPatternProvider時傳回這些模式提供者。
引發事件 呼叫 AutomationInteropProvider 的其中一個靜態方法,來引發用戶端可以接聽的事件。
在片段內啟用導覽和聚焦功能 為片段內的每個項目實作 IRawElementProviderFragment 。 (項目若不屬於片段,則不需要)。
可讓您在片段中將焦點放在子項目和尋找子項目 實作 IRawElementProviderFragmentRoot。 (項目若不是片段根,則不需要)。

非 WPF 提供者中的屬性值

自訂控制項的 UI 自動化提供者必須支援某些屬性,而這些屬性可由自動化系統以及用戶端應用程式使用。 對於裝載於視窗 (HWND) 的元素,UI 自動化可以從預設視窗提供者擷取某些屬性,但必須從自訂提供者取得其他屬性。

以 HWND 為基礎的控制項的提供者通常不需要提供下列屬性 (以欄位值識別):

注意

簡單項目的 RuntimeIdProperty 或裝載在視窗中之片段根的項目取自於視窗;不過,根之下的片段項目 (例如清單方塊中的清單項目) 必須提供自己的識別項。 如需詳細資訊,請參閱GetRuntimeId

應該針對 Windows Forms 控制項中裝載的提供者傳回 IsKeyboardFocusableProperty。 在此情況下,預設視窗提供者可能無法擷取正確值。

NameProperty 通常由主機提供者所提供。 例如,如果自訂控制項衍生自 Control,則名稱衍生自控制項的 Text 屬性。

如需範例程式碼,請參閱 Return Properties from a UI Automation Provider

非 WPF 提供者中的事件

UI 自動化提供者應該引發事件,將 UI 狀態中的變更通知用戶端應用程式。 下列方法會用於引發事件。

方法 描述
RaiseAutomationEvent 引發各種事件,包括由控制項模式觸發的事件。
RaiseAutomationPropertyChangedEvent UI 自動化屬性變更後,即會引發事件。
RaiseStructureChangedEvent UI 自動化樹狀結構的結構變更後,即會引發事件,例如,移除或新增元素。

事件的目的在於通知用戶端在使用者介面 (UI) 中發生某種情況,活動是否由 UI 自動化系統本身觸發。 例如,每當透過直接使用者輸入,或是藉由呼叫 InvokedEvent 的應用程式叫用控制項時,應該引發 Invoke所識別的事件。

若要最佳化效能,提供者可以選擇性地引發事件,或如果沒有註冊任何用戶端應用程式來接收事件,則完全不引發任何事件。 下列方法會用於最佳化。

方法 描述
ClientsAreListening 這個靜態屬性會指定是否有任何用戶端應用程式已訂閱 UI 自動化事件。
IRawElementProviderAdviseEvents 提供者在片段根上實作此介面,可讓提供者在用戶端針對片段上的事件註冊和取消註冊事件處理常式時接到通知。

非 WPF 提供者導覽

簡單控制項 (例如裝載於視窗 (HWND) 的自訂按鈕) 的提供者不需要支援 UI 自動化樹狀結構內的導覽。 項目之間的導覽是由主控視窗的預設提供者處理,而預設提供者則於 HostRawElementProvider的實作中指定。 不過,當您實作複雜自訂控制項的提供者時,您必須支援片段的根節點與子系之間的導覽,以及同層級節點之間的導覽。

注意

根以外的片段項目必須從 null 傳回 HostRawElementProvider參考,因為它們不會直接裝載在視窗中,而且沒有預設提供者可支援項目之間的導覽。

片段的結構取決於您的 Navigate實作。 對於每個片段的可能方向,此方法會傳回該方向中項目的提供者物件。 如果該方向中沒有任何項目,此方法會傳回 null 參考。

片段根僅支援導覽至子項目。 例如,當方向為 FirstChild時,清單方塊會傳回清單中的第一個項目,而當方向為 LastChild時,則傳回最後一個項目。 片段根目錄不支援導覽至父代或同層級;這是由主控視窗提供者處理。

不是根的片段項目必須支援導覽至父代,以及導覽至任何同層級和其具有的子系。

非 WPF 提供者重設父代

實際上快顯視窗是最上層視窗,因此預設為出現在 UI 自動化樹狀結構,以做為桌面的子系。 不過,在許多情況下,快顯視窗在邏輯上是一些其他控制項的子系。 例如,下拉式方塊的下拉式清單在邏輯上是下拉式方塊的子系。 同樣地,功能表快顯視窗在邏輯上是功能表的子系。 UI 自動化提供支援,以重設快顯視窗的父代,讓它們看起來似乎是相關聯控制項的子系。

若要重設快顯視窗的父代:

  1. 建立快顯視窗的提供者。 這需要預先知道快顯視窗的類別。

  2. 如往常般實作該快顯視窗的所有屬性和模式,好似它本身就是控制項。

  3. 實作 HostRawElementProvider 屬性,好讓它傳回取自 HostProviderFromHandle的值,其中參數是快顯視窗的視窗控制代碼。

  4. 實作快顯視窗和其父代的 Navigate ,以便可以適當處理從邏輯父代到邏輯子系的導覽,以及同層級子系之間的導覽。

當 UI 自動化遇到快顯視窗時,它會辨識是否以預設值取代導覽,並在遇到快顯視窗為桌面的子系時,略過快顯視窗。 相反地,節點只能透過片段來連接。

重設父代不適合控制項可以裝載任何類別之視窗的情況。 例如,rebar 可在其群組列中裝載任何類型的 HWND。 為了處理這些情況,UI 自動化支援替代形式的 HWND 重新配置,如下一節所述。

非 WPF 提供者重設配置

UI 自動化片段可能包含兩個或多個元素,而每一個都包含在一個視窗 (HWND) 中。 因為每個 HWND 都有自己的預設提供者,將 HWND 視為包含 HWND 的子系,所以 UI 自動化樹狀結構會根據預設將 HWND 顯示在片段中,做為父視窗的子系。 在大部分情況下,這是所需的行為,但有時候,可能會造成混淆,因為它不符合 UI 的邏輯結構。

rebar 控制項就是這種情況的好範例。 Rebar 包含群組列,其中每一個可以輪流包含 HWND 型控制項,例如工具列、編輯方塊或下拉式方塊。 Rebar HWND 的預設視窗提供者會將群組列控制項 HWND 視為子系,而且 rebar 提供者也會將群組列視為子系。 因為 HWND 提供者和 rebar 提供者會一起運作,並且結合其子系,所以群組列和 HWND 型控制項會顯示為 rebar 的子系。 不過,在邏輯上只有群組列應該顯示為 rebar 的子系,而且每個群組列提供者應該要與其包含之控制項的預設 HWND 提供者配合。

為了達成此目的,rebar 的片段根提供者會公開一組代表群組列的子系。 每個群組列都有可能公開屬性和模式的單一提供者。 在實作 HostRawElementProvider時,群組列提供者會傳回控制項 HWND 的預設視窗提供者,而取得此提供者的方式為呼叫 HostProviderFromHandle,並傳入控制項的視窗控制代碼。 最後,rebar 的片段根提供者會實作 IRawElementProviderHwndOverride 介面,以及在實作 GetOverrideProviderForHwnd 時,它會傳回指定的 HWND 中包含之控制項的適當群組列提供者。

另請參閱