我有一个COM-visible方法,如下所示:
Public Sub SomeMethod(someControl as Object)
On Error Goto ErrHandler
Dim someSpecificControl as SpecificControl
MsgBox TypeOf someControl is Control
MsgBox TypeOf someControl is SpecificControl
On Error Resume Next
Set someSpecificControl = someControl
On Error Goto ErrHandler
if someSpecificControl is Nothing then
Exit Sub
end if
' do stuff to the control
End Sub
其他组件会调用此方法(即通过COM)并传入类型为SpecificControl
的控件。
我的问题是,当通过调试器运行时,参数化控件似乎不是正确的类型,即它在'cast'失败之后退出子例程,而我预期它不会。
使用TypeOf
我已经验证参数化对象是Control类型(如上所述)但我无法弄清楚为什么它被传入 - 显然 - 不正确。在调试器外部运行时似乎行为正常 - 但我不能确定(因此这个问题)。
任何人都可以对此有所了解吗?在拳击拆箱过程中,控件是否已经 - 某种程度上 - 被破坏了?有没有更好的方法呢?
编辑:我使用了Kris Erickson建议的TypeName
并获得了一些有趣的结果:
MsgBox TypeName(someControl)
MsgBox "someControl is of type SpecificControl: " & TypeOf someControl is SpecificControl
MsgBox "someControl is of type UserControl: " & TypeOf someControl is UserControl
MsgBox "someControl is of type Control: " & TypeOf someControl is Control
我明白了:
SpecificControl
someControl is of type SpecificControl: False
someControl is of type UserControl: False
someControl is of type Control: True
我想我唯一能做的就是避免将UserControl作为参数传递。
答案 0 :(得分:3)
我使用VBControlExtender
作为参数类型
Public Sub SomeMethod(someControl as VBControlExtender)
然后我得到像这样的引用
Dim someSpecificControl as SpecificControl Dim someSpecificControlExt as VBControlExtender Set someSpecificControl = someControl.object Set someSpecificControlExt = someControl
然后使用someSpecificControlExt
访问Left
,TabIndex
,TabStop
,Name
,Move
等扩展程序的属性和{ {1}}访问我的用户控件的特定方法/属性。
仅供参考,代码的行为取决于用户控件是在当前项目中实现还是在ocx中引用。我也在使用Matt Curlands direct user control access hack,这允许我这样做
Dim someSpecificControl as DirectSpecificControl
以便早期访问someSpecificControl
道具/方法。
这就是我从控件中获取someSpecificControl
(扩展器)的方法:
Public Function GetExtendedControl(oCtl As IUnknown) As VBControlExtender Dim pOleObject As IOleObject Dim pOleControlSite As IOleControlSite On Error Resume Next Set pOleObject = oCtl Set pOleControlSite = pOleObject.GetClientSite Set GetExtendedControl = pOleControlSite.GetExtendedControl On Error GoTo 0 End Function
这就是我获取VB6用户控件的内部someSpecificControlExt
的方法:
Public Function GetUserControl(oObj As Object) As UserControl Dim pControl As UserControl Call CopyMemory(pControl, ObjPtr(oObj), 4) Set GetUserControl = pControl Call CopyMemory(pControl, 0&, 4) End Function
引用UserControl
返回有一个非常奇怪的GetUserControl
实现 - 似乎QueryInterface
接口专门针对UserControl
。
答案 1 :(得分:1)
我不知道为什么会这样,但我知道UserControl在VB6中是半魔术。如果你通过它的实际类型将UserControl传递给一个函数,它会丢失它的所有UserControl基类(我知道,VB6没有继承,但是在创建UserControl时你需要某些特性)。
所以,如果你
Private Sub AdjustControlProperties(oControl as MyUserControl)
...
End Sub
一旦控件离开你的子程序,它将表现为一个Control,而不是UserControl(你将无法访问UserControl属性,并且尝试访问它们将导致错误)。 VB6中的一个非常奇怪的错误,一个引起大量拉动头发的问题。
Private Sub AdjustControlProperties(oControl as Object)
...
End Sub
一切都很好。我的猜测是你是正确的,UserControls是盒装的,没有装箱,因为Control不是UserControls。类型检查的唯一解决方案是使用
TypeName()
知道它是什么类型,因为它不会被破坏。