托管 UI 自动化无窗口 ActiveX 控件
了解如何创建能够托管实现 Microsoft UI 自动化的无窗口 Microsoft ActiveX 控件的控件容器。 通过使用此处所述的步骤,可以确保控制容器中托管的任何UI 自动化无窗口控件都可以通过辅助技术 (AT) 客户端应用程序进行访问。
需要了解的事项
技术
先决条件
- C/C++
- Microsoft Win32 和组件对象模型 (COM) 编程
- 无窗口 ActiveX 控件
- UI 自动化提供程序
Instructions
步骤 1:代表无窗口控件提供 IRawElementProviderSimple 接口。
每当系统需要 IRawElementProviderSimple 指针作为无窗口控件的根时,系统会查询控件容器。 为了检索指针,容器调用无窗口控件的 IServiceProvider::QueryService 方法的实现。
如果控件容器具有UI 自动化实现,它可以返回指向系统的无窗口控件的 IRawElementProviderSimple 指针。
如果控件容器具有 Microsoft Active Accessibility 实现,请调用 UiaIAccessibleFromProvider 函数以获取表示控件的 IAccessible 接口指针,然后将 IAccessible 接口指针返回到系统。
步骤 2:实现 IRawElementProviderWindowlessSite 接口。
控件容器实现 IRawElementProviderWindowlessSite 接口,使基于UI 自动化的无窗口控件能够传达其辅助功能信息。
实现 IRawElementProviderWindowlessSite::GetRuntimeIdPrefix。
无窗口控件片段必须为自身创建唯一的运行时 ID。 为了创建其运行时 ID,无窗口控件片段通过调用控件站点的 GetRuntimeIdPrefix 方法检索前缀值,然后将相对于无窗口控件中所有其他片段唯一的整数值追加到前缀。
无窗口控件的控制站点应通过形成包含常量 UiaAppendRuntimeId 的 SAFEARRAY,后跟站点唯一的整数值来实现 GetRuntimeIdPrefix 方法。
此示例演示如何返回无窗口控件的运行时 ID 前缀。
IFACEMETHODIMP CProviderWindowlessSite::GetRuntimeIdPrefix( SAFEARRAY **ppsaPrefix) { if (ppsaPrefix == NULL) { return E_INVALIDARG; } // m_siteIndex is the index of the windowless control's // site. It is defined by the control container. int rId[] = { UiaAppendRuntimeId, m_siteIndex }; SAFEARRAY *psa = SafeArrayCreateVector(VT_I4, 0, 2); if (psa == NULL) { return E_OUTOFMEMORY; } for (LONG i = 0; i < 2; i++) { SafeArrayPutElement(psa, &i, (void*)&(rId[i])); } *ppsaPrefix = psa; return S_OK; }
实现 IRawElementProviderWindowlessSite::GetAdjacentFragment 方法。
实现UI 自动化的控件必须返回指向控件的父片段提供程序的指针。
若要返回片段的父级,实现 IRawElementProviderFragment 接口的对象必须能够实现 Navigate 方法。 对于无窗口控件,实现 Navigate 是困难的,因为控件可能无法确定它在父对象的可访问树中的位置。 IRawElementProviderWindowlessSite::GetAdjacentFragment 方法使无窗口控件能够查询其站点中的相邻片段,然后将该片段返回到调用 Navigate 的客户端。
此示例演示控件容器如何检索无窗口控件的父片段。
IFACEMETHODIMP CProviderWindowlessSite::GetAdjacentFragment( enum NavigateDirection direction, IRawElementProviderFragment **ppFragment) { if (ppFragment == NULL) { return E_INVALIDARG; } *ppFragment = NULL; HRESULT hr = S_OK; switch (direction) { case NavigateDirection_Parent: { IRawElementProviderSimple *pSimple = NULL; // Call an application-defined function to retrieve the // parent provider interface. hr = GetParentProvider(&pSimple); if (SUCCEEDED(hr)) { // Get the parent's IRawElementProviderFragment interface. hr = pSimple->QueryInterface(IID_PPV_ARGS(ppFragment)); pSimple->Release(); } } break; case NavigateDirection_FirstChild: case NavigateDirection_LastChild: hr = E_INVALIDARG; break; // Ignore NavigateDirection_NextSibling and NavigateDirection_PreviousSibling // because there are no adjacent fragments. default: break; } return hr; }
步骤 3:可选:实现 IRawElementProviderHostingAccessibles 接口。
如果控件容器具有UI 自动化提供程序实现,该实现是辅助功能树的根,其中包含支持 Microsoft Active Accessibility 的无窗口 ActiveX 控件,则实现 IRawElementProviderHostingAccessibles 接口。 IRawElementProviderHostingAccessibles 接口有一个方法 GetEmbeddedAccessibles,该方法检索控件容器托管的所有基于 Active Accessibility 的无窗口 ActiveX 控件的 IAccessible 接口指针。
相关主题