将UIAutomation提供程序添加到Delphi控件(特别是网格)
我们的VCL Delphi应用程序有许多网格,我们需要通过UIAutomation开始交互。 有很多问题,不是最少的,TStringGrid没有实现任何IUIAutomation模式(IGridProvider或ITableProvider,或者就此而言甚至是IValueProvider)。
我试图找出我需要添加到TStringGrid以允许它实现提供程序(在.NET中的System.Windows.Automation.Provider命名空间中)。
尽管我无法提供实现TStringGrid所需的自动化功能所需的具体步骤,但我可以根据您的评论来说,您几乎拥有了所需的一切。
您发现的文章描述了Win32非托管代码的UI Automation支持的基本实现,这是一个很好的开始。
然后,通过UIAutomationCore.DLL中的IDL暴露的问题以及未通过IDIA暴露的问题由以下事实来解决:所讨论的DLL本身意图被非托管代码使用。 它本身不包含托管代码。 至少不会涉及非托管用例。
包含的内容是由IDL描述的COM接口,还有一些由DLL简单导出的函数。 据我所知,IDL并没有描述DLL的导出表。 即使它能够这样做,在这个DLL的情况下它也不会(至少在所有情况下都是如此)。
例如,您提到的UiaHostProviderFromHwnd()函数是一个简单的DLL导出。 以这种方式导出的一些附加功能在本MSDN博客文章中描述,描述为该库创建.net interop接口。 在那篇文章中,他们被称为“平面API方法”。
使用PE资源管理器我可以看到由UIAutomationCore.dll库导出的81个这样的函数。
不幸的是,DLL导出表不会描述任何导出函数的参数或返回类型,只有名称。 因此,除了类型库(由IDL生成)之外,还需要查找并转换UIAutomationCore.h头文件以便与Delphi(即Pascal)一起使用。
然后,您应该拥有所有需要为您所需的任何VCL控件实现UI Automation功能的应用程序。
这是我的步骤...
(实际文件太大而无法发布所有文件,所以这是对主要观点的一种提升)。
此外 - 这仍然有重大问题,可能是我自己制造的,但对我来说取得进展已足够。
function UiaHostProviderFromHwnd(hwnd: HWND; provider: IRawElementProviderSimple): LRESULT; stdcall; external 'UIAutomationCore.dll' name 'UiaHostProviderFromHwnd';
function UiaReturnRawElementProvider(hwnd: HWND; wParam: WPARAM; lParam: LPARAM; element : IRawElementProviderSimple) : LRESULT; stdcall; external 'UIAutomationCore.dll' name 'UiaReturnRawElementProvider';
// IRawElementProviderSimple function Get_ProviderOptions(out pRetVal: ProviderOptions): HResult; stdcall; function GetPatternProvider(patternId: SYSINT; out pRetVal: IUnknown): HResult; stdcall; function GetPropertyValue(propertyId: SYSINT; out pRetVal: OleVariant): HResult; stdcall; function Get_HostRawElementProvider(out pRetVal: IRawElementProviderSimple): HResult; stdcall; // ISelectionProvider function GetSelection(out pRetVal: PSafeArray): HResult; stdcall; function Get_CanSelectMultiple(out pRetVal: Integer): HResult; stdcall; function Get_IsSelectionRequired(out pRetVal: Integer): HResult; stdcall;
这些实施如下。
function TAutomationStringGrid.Get_ProviderOptions( out pRetVal: ProviderOptions): HResult; begin pRetVal:= ProviderOptions_ClientSideProvider; Result := S_OK; end; function TAutomationStringGrid.GetPatternProvider(patternId: SYSINT; out pRetVal: IInterface): HResult; begin pRetval := nil; if (patternID = UIA_SelectionPatternId) then begin result := QueryInterface(ISelectionProvider, pRetVal); end else result := S_OK; end; function TAutomationStringGrid.GetPropertyValue(propertyId: SYSINT; out pRetVal: OleVariant): HResult; begin if(propertyId = UIA_ControlTypePropertyId) then begin TVarData(pRetVal).VType := varWord; TVarData(pRetVal).VWord := UIA_DataGridControlTypeId; end; result := S_OK; end; function TAutomationStringGrid.Get_HostRawElementProvider( out pRetVal: IRawElementProviderSimple): HResult; begin result := UiaHostProviderFromHwnd (self.Handle, pRetVal); end; function TAutomationStringGrid.GetSelection(out pRetVal: PSafeArray): HResult; begin end; function TAutomationStringGrid.Get_CanSelectMultiple( out pRetVal: Integer): HResult; begin end; function TAutomationStringGrid.Get_IsSelectionRequired( out pRetVal: Integer): HResult; begin end;
为了实际获得控件,需要处理WM_GETOBJECT消息...
procedure WMGetObject(var Message: TMessage); message WM_GETOBJECT;
这是实施如下..
procedure TAutomationStringGrid.WMGetObject(var Message: TMessage); begin if (Message.Msg = WM_GETOBJECT) then begin QueryInterface(IID_IRawElementProviderSimple, FRawElementProviderSimple); message.Result := UiaReturnRawElementProvider(self.Handle, Message.WParam, Message.LParam, FRawElementProviderSimple); end else Message.Result := DefWindowProc(self.Handle, Message.Msg, Message.WParam, Message.LParam); end;链接地址: http://www.djcxy.com/p/84561.html
上一篇: Adding UIAutomation Providers to Delphi controls (specifically grids)
下一篇: How to fetch the filename from CSV and insert it into one of columns of a table