用于VB6应用程序的UIAutomation [英] UIAutomation for VB6 applications

查看:96
本文介绍了用于VB6应用程序的UIAutomation的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为背景,我试图为VB6应用程序添加UIAutomation支持并且已经陷入僵局。我在C ++中编写了几个UIAutomation提供程序,它们调用控制方法来提供必要的控制和查询功能,并在主exe和VB6应用程序中添加了代码,每个dll都使用控件的中央uiprovider工厂注册exe或dll用于将提供程序附加到控件的hWnds和类名。 SOme VB6控件可以由内置于UiAutomation的默认Win32提供程序提供服务,但不是全部。遗憾的是,默认的automationid没有为表单窗口设置,并且是控件的控件ID,VB6使用父表单中定义的顺序依次动态分配id。当添加一个控件时,将tit放在列表的头部,这样就可以更改表单上的所有其他控件ID,因此需要任何uiautomation引用也需要更改。



通过创建我自己的提供程序并获得对应用程序表单和控件的访问权限,我可以更改此设置,以便控件names代替自动化ID,并且我可以使用控制接口来访问和驱动控件属性。要做到这一点,我需要能够将窗口句柄映射到相关的VB6控件。



从我最初阅读VB6文档我相信全球表单集合将允许我枚举应用程序中的所有活动表单,但这似乎不是真的,每个dll / ocx似乎有自己独立的表单集合,但这很容易通过获取每个DLL / ocx和exe注册我的提供商工厂。然后我可以枚举窗体上的控件来执行对给定窗口句柄的搜索,并为窗体/控件提供枚举器。此时我遇到了UserControls的问题,请参阅下面的简化代码说明问题,真正的代码有错误处理以满足无窗口控件的需要,并且不会将其窗口句柄作为属性公开。



函数SearchForm(theForm as Form,long hWnd)As Object

Dim theControl as Control



For Each theControl In theForm.Controls'迭代表格上的控件

如果theControl.hWnd = hWnd那么

SearchForm = theControl'如果找到目标则返回它

退出

else如果是IsUserControl(theControl)那么'使用测试windows类名因为TypeOf

'不起作用

Dim theUserControl As UserControl

Dim theResult As Control

'********

Se t theUserControl = theControl'如果我们找到了UserControl搜索它

'即使Control是

'引用UserControl这个Set也失败

'出于同样的原因,我无法使用TypeOf检测

'用户控件。

'**********

设置theResult =搜索(theUserControl,hWnd)'递归搜索UserControl孩子

'控件

如果Not theResult则什么都没有那么

设置SearchForm = theResult

退出

结束如果

结束如果

下一个theControl

结束功能



我提取了i类型各种VB6实体的nfo并尝试用C ++解决这个问题,但似乎控件不允许通过QueryInterface()访问_UserControl接口。



同时检索到的typeinfo来自VB6.OLB似乎很奇怪并且调用暴露的方法经常崩溃或返回奇数据,就像typeinfo没有反映实际的实现。



有没有人有更好的将hWnds映射到VB6控件的解决方案或者知道如何从Control切换到UserControl以枚举其子节点?



谢谢Andy Hitchins

By way of background I am trying to add UIAutomation support for VB6 applications and have reached an impasse. I have written several UIAutomation providers in C++ that invoke control methods to provide the necessary control and query functions and have added code to the VB6 app in the main exe and each dll that registers the exe or dll with a central uiprovider factory that uses the control hWnds and classnames to attach a provider to the control. SOme VB6 controls can be serviced by the default Win32 providers already built in to UiAutomation but not all. Unfortunately the default automationid is not set in for form windows and is the control id for controls and VB6 dynamically allocates the ids sequentially using the defined order within the parent form. When a control is added tit is placed at the head of the list so changing all other control ids on the form thus requiring any uiautomation references to require changing as well.

By creating my own providers and gaining access to the application forms and controls I am able to change this so that the control "names" are the automation id instead and and I can use the control interfaces to access and drive control attributes. To do this I need to be able to map window handles to the associated VB6 controls.

From my initial reading of the VB6 documentation I believed that the global "Forms" collection would allow me to enumerate "ALL" active forms within an application but this appears not to be true, each dll/ocx seems to have its own independent form collection but this was easy to work around by getting each dll/ocx and the exe to register with my provider factory. Then I can enumerate controls on a form to execute the search for a given window handle and provide an enumerator for forms/controls. At this point I hit the problem of UserControls, See simplified code below which illustrates the problem, real code has error handling to cater for windowless controls and thse which do not expose their window handle as a property.

Function SearchForm(theForm as Form, long hWnd) As Object
Dim theControl as Control

For Each theControl In theForm.Controls ' Iterate over controls on Form
If theControl.hWnd = hWnd Then
SearchForm = theControl ' If found target return it
Exit For
else If IsUserControl(theControl) Then ' Uses test windows classname because TypeOf
' does not work
Dim theUserControl As UserControl
Dim theResult As Control
' ********
Set theUserControl = theControl ' If we have found a UserControl search it
' This Set Fails even if Control is
' referencing a UserControl
' for same reason I cannot use TypeOf to detect
' user controls.
' **********
Set theResult = Search(theUserControl, hWnd) ' recursive search UserControl child
' controls
If Not theResult Is Nothing Then
Set SearchForm = theResult
Exit For
End If
End If
Next theControl
End Function

I have extracted the type info of various VB6 entities and tried to solve this in C++ but it appears that controls do not allow access to the _UserControl interface via QueryInterface().

Also the typeinfo retrieved from VB6.OLB seems strange and calling exposed methods often crashes or returns odd data, it is like the typeinfo does not reflect the actual implementation.

Does anyone have a better solution for mapping hWnds to VB6 controls or know how to switch from "Control" to "UserControl" in order to enumerate its children?

Thanks Andy Hitchins

推荐答案

这篇关于用于VB6应用程序的UIAutomation的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆