将userform声明为Object与MSForms.Userform之间的区别?

时间:2014-10-16 15:39:14

标签: vba vb6 userform

只是一个我似乎无法找到答案的问题。

我以编程方式创建了一个用户表单,并且我发现如果我将对象声明为类型" MSForms.Userform"似乎没有办法设置高度和宽度,因为这些属性不存在,而insideheight / insidewidth是只读属性。

我发现如果我将其声明为通用类型" object",我可以设置高度和宽度属性并完全按照我的意愿使用它。

因此,在初始化对象后,我检查了本地窗口,差异似乎是:

  • 当声明为类型"对象"它将初始化为类型" UserForm1"的实例。
  • 当声明为类型" MSForms.Userform"它将初始化为" UserForm"
  • 类型的实例

所以我的问题是,使用不同的声明语句有什么区别?

谢谢!

编辑:添加了一些示例代码,以便您可以看到对象在不同声明时的行为方式有何不同。
(我无法正确显示此代码块 - 即使声明为基本语言)

Sub TestUserForm()  
'NOTE:  You need to add a reference to Microsoft Visual Basic
'       for Applications Extensibility 5.3  

'Declare variables  
    Dim oForm           As MSForms.UserForm  
    Dim oForm1          As Object  
    Dim oComp           As VBComponent  
    Dim oComp1          As VBComponent  

'Create new form objects in the VBA project programmatically  
Set oComp = Application.VBE.ActiveVBProject.VBComponents.Add(ComponentType:=vbext_ct_MSForm)  
Set oComp1 = Application.VBE.ActiveVBProject.VBComponents.Add(ComponentType:=vbext_ct_MSForm)  

'Initailize an object of each new form  
    Set oForm = VBA.UserForms.Add(oComp.Name)  
    Set oForm1 = VBA.UserForms.Add(oComp1.Name)  

'Compare what happends when trying to set the width and height properties  
    With oForm1     'This works  
        .Height = 200  
        .Width = 100  
    End With  

    With oForm1     'This does not work  
        .Properties("Width") = 100  
        .Properties("Height") = 200  
    End With  

    With oForm      'This does not work  
        .Height = 200  
        .Width = 100  
    End With  

    With oForm      'This does not work  
        .Properties("Width") = 100  
        .Properties("Height") = 200  
    End With  

'Remove the forms from the project  
    Application.VBE.ActiveVBProject.VBComponents.Remove oComp  
    Application.VBE.ActiveVBProject.VBComponents.Remove oComp1  
End Sub  

3 个答案:

答案 0 :(得分:8)

将组件导入项目时,它将分别命名为UserForm1 UserForm2

  

oForm == UserForm1

     

oForm1 == UserForm2

现在,看MSDN docs for Object,我们发现:

  

在过程运行之前,如果不知道特定对象类型,则可以使用Object数据类型声明对象变量。使用Object数据类型创建对任何对象的通用引用。

你已经声明了这样的变量:

Dim oForm           As MSForms.UserForm  
Dim oForm1          As Object  

初始化对象时会发生什么,oForm被初始化为UserForm,而运行时确定 Object oForm1是UserForm1的一个实例,这是不一样的。

在初始化之前尝试更改oForm1的组件名称,您应该很快就会看到差异。

现在 ,如果您希望声明类型安全性为通用表单 ,则需要访问Width属性,您可以将UserForm强制转换为Object并像这样访问它。

Dim FormAsForm As UserForm
Dim FormAsObject As Object

Set FormAsForm = New UserForm1
Set FormAsObject = FormAsForm

FormAsObject.Width = 200

Debug.Print TypeName(FormAsForm)
Debug.Print TypeName(FormAsObject)

这是我们在实现多个接口时经常使用的技巧。编译器只允许您使用在声明类对象的特定类型中定义的属性。


那有什么区别?实际上,在将事物声明为Object时,您没有智能感知。你也没有类型安全。这样做完全有效(虽然不推荐。)

Dim foo As New Baz
Dim bar As New Qux
Dim var As Object

Set var = foo
Set var = bar

当您使用后期绑定时,对象确实非常方便,以避免添加对项目的引用。如果没有添加引用,您将被迫使用未知类型。

Dim xl As Object
Set xl = CreateObject("Excel.Application")

另一个很大的区别是你将它留给运行时来确定变量将是什么类型的对象。正如您所发现的,它有时(很少,但有时)会产生令人惊讶的结果。

答案 1 :(得分:1)

我认为你对这种差异有了答案:

  • 一个是UserForm1类的UserForm对象,包装在一个Object对象(Type Object / UserForm1)中,可以在proc中设置为其他任何东西,
  • ,另一个是UserForm2类的UserForm对象。

但编译器只允许使用类对象声明为的类型的现有属性/方法:

  • 对象具有.Width和.Height属性,因此oForm1将允许您访问VBE组件UserForm2的实例化形式的这些属性(看一下HERE以进一步了解这一点),但oForm赢了'吨。
  • UserForms有一个.Show / .Hide方法,因此将有oForm显示VBE组件UserForm1的实例化/加载形式,但oForm1不会。

我做了一些测试,我只是想指出我认为纠正的程序宁愿:

Dim FormAsForm As **UserForm1***
Dim FormAsObject As Object

Set FormAsForm = New UserForm1
Set FormAsObject = FormAsForm

FormAsObject.Width = 200

Debug.Print TypeName(FormAsForm)
Debug.Print TypeName(FormAsObject)

将FormAsForm声明为UserForm1,而不是UserForm,这会导致我的错误:

  

运行时错误'438':对象不支持此属性或方法

然而,使用它,在使用.Show加载并显示一次FormAsForm之后,然后将Unloaded,FormAsForm从TypeForm11 / UserForm11下载到UserForm11 / UserForm,并且无法再显示.Show。任何应该工作的方法都会导致这个错误:

  

错误'-2147418105':自动化错误

     

错误'-2147418105':Erreur Automation:L'appelé(serveur [pas application serveur])n'est pas disponible et disparu; aucune connexion n'est valide。 L'Appel a peut-êtreétéexécuté。

当然,我刚给出的变量类型是从Locals VBE窗口中读取的,因为?TypeName(FormAsForm)只会带来:

  

运行时错误'13':输入不匹配

对于记录,?TypeName(FormAsObject)在向下转换后返回UserForm,而.Show方法会导致相同的“自动化错误”。

empty

这一部分,我无法解释......

答案 2 :(得分:0)

因此,除非我在这里错过我的猜测,否则MSFORMS.UserForm是其他某些东西的子类(也许类似于VB6 Form类?),以及它在按尺寸标注时可以正确处理的其他属性和方法。对象(.Hide,.Show,.Visible,以我到目前为止所知道的命名)既不是Userform类接口的一部分,也不是文档化的ANY-DAMN-WHERE-AT-ALL(而且我不会除了阅读有关UserForms的在线问题/评论外,我不了解上面列出的内容! ...必须派生自UserForm继承的基类?

太糟糕了,我们看不到基类是什么,因为这样我们就可以找到有关我们可以使用的其他功能的实际线索(谁知道,可能有.Parent,.Properties或其他有趣的东西)似乎没有人知道的“在那里”的东西。