用户定义类型(UDT)作为类模块中公共Sub的参数(VB6)

时间:2009-06-10 14:37:12

标签: vba vb6 user-defined-types

我试图解决这个问题,但找不到任何解决方案。我在普通模块中定义了UDT,并希望将其用作类模块中Public Sub中的参数。然后我得到一个编译错误:

  

只有公共对象模块中定义的公共用户定义类型可以用作类模块的公共过程的参数或返回类型,或者用作公共用户定义类型的字段

然后我尝试在类中移动我的UDT,声明为Private。我得到了这个编译错误:

  

私有枚举和用户定义的类型不能用作公共过程,公共数据成员或公共用户定义类型字段的参数或返回类型。

我最终尝试在类中声明它为Public,并得到此编译错误:

  

无法在私有对象模块中定义公共用户定义的类型。

那么有没有办法让公共UDT用作类中公共子的参数?

7 个答案:

答案 0 :(得分:18)

将sub定义为Friend范围。这对VB6类的编译很好。

Private Type testtype
  x As String
End Type


Friend Sub testmethod(y As testtype)

End Sub

根据您的错误消息,您的课程显示为私有。如果您确实希望您的类是公共的 - 即您正在制作ActiveX exe或DLL并且您希望客户端能够访问该子类 - 那么只需将类型和子公共。同时制作。

答案 1 :(得分:10)

  

有没有办法让公众参与   UDT用作公共参数   在一个班级?

总之,没有。您可以使用Classic VB代码最接近的是创建一个复制UDT并使用它的类。这里肯定有优势,但如果您需要将其传递给API,那么您就会受到冲击。

另一种选择是在类型库中定义UDT。如果这样做,它可以用作公共方法的参数。

答案 2 :(得分:9)

好的,这是怎么做的,如果我可以让我的猫离开我,就是这样。

在Form1中(上面有一个命令按钮):

Option Explicit
'
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal dst As Long, ByVal src As Long, ByVal nBytes As Long)
'

Private Sub Command1_Click()
' Okay, this is what won't work in VB6:
'     Dim MyUdt1 As MyUdtType   ' Declare a variable with a publicly defined UDT (no problem).
'     Form2.Show                ' We could have created some object with a class.  This was just easier for the demo.
'           INSIDE OF FORM2:
'               Public Sub MySub(MyUdt2 As MyUdtType)   ' It won't even let you compile this.
'                   Msgbox MyUdt2.l
'                   MyUdt2.l = 5
'               End Sub
'     Form2.MySub MyUdt1                                ' You'll never get this far.
'     Unload Form2
'     Msgbox MyUdt1.l
'
' The following is a way to get it done:
'
Dim MyUdt1 As MyUdtType         ' Declare a variable with a publicly defined UDT (no problem).
Dim ReturnUdtPtr As Long        ' Declare a variable for a return pointer.
MyUdt1.l = 3                    ' Give the variable of our UDT some value.
Form2.Show                      ' Create our other object.
'
' Now we're ready to call our procedure in the object.
' This is all we really wanted to do all along.
' Notice that the VarPtr of the UDT is passed and not the actual UDT.
' This allows us to circumvent the no passing of UDTs to objects.
ReturnUdtPtr = Form2.MyFunction(VarPtr(MyUdt1))
'
' If we don't want anything back, we could have just used a SUB procedure.
' However, I wanted to give an example of how to go both directions.
' All of this would be exactly the same even if we had started out in a module (BAS).
CopyMemory VarPtr(MyUdt1), ReturnUdtPtr, Len(MyUdt1)
'
' We can now kill our other object (Unload Form2).
' We probably shouldn't kill it until we've copied our UDT data
' because the lifetime of our UDT will be technically ended when we do.
Unload Form2                    ' Kill the other object.  We're done with it.
MsgBox MyUdt1.l                 ' Make sure we got the UDT data back.
End Sub

在form2中(无需控件)。 (这可能就像用类创建的对象一样容易。):

    Option Explicit
'
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal dst As Long, ByVal src As Long, ByVal nBytes As Long)
'

Public Function MyFunction(ArgUdtPtr As Long) As Long
' Ok, this is how we get it done.
' There are a couple of things to notice right off the bat.
' First, the POINTER to the UDT is passed (using VarPtr) rather than the actual UDT.
' This way, we can circumvent the restriction of UDT not passed into objects.
' Second, the following MyUdt2 is declared as STATIC.
' This second point is important because the lifetime of MyUdt2 technically ends
' when we return from this function if it is just DIMmed.
' If we want to pass changes back to our caller, we will want to have a slightly longer lifetime.
Static MyUdt2 As MyUdtType
' Ok, we're here, so now we move the argument's UDT's data into our local UDT.
CopyMemory VarPtr(MyUdt2), ArgUdtPtr, Len(MyUdt2)
' Let's see if we got it.
MsgBox MyUdt2.l
' Now we might want to change it, and then pass back our changes.
MyUdt2.l = 5
' Once again, we pass back the pointer, because we can't get the actual UDT back.
' This is where the MyUdt2 being declared as Static becomes important.
MyFunction = VarPtr(MyUdt2)
End Function

最后,这是一个模块(BAS)文件。

    Option Explicit
'
' This is just the UDT that is used for the example.
Public Type MyUdtType
    l As Long
End Type
'

答案 3 :(得分:2)

将UDT作为参考参数传递,它将起作用。 :)

'method in the class

Public Sub CreateFile(ByRef udt1 As UdtTest)

End Sub

答案 4 :(得分:1)

我有相同的错误消息,在检查应用程序后,我发现在类的属性窗口中,“Instancing”设置被设置为“1 - Private”,用于引用的对象。我将其更改为“5 - MultiUse”并得到相同的错误消息。然后我回到项目模块的一个版本,之后我添加了引用的对象并再次添加了项目 - 它默认为“1 - Private”。在进行任何其他操作之前,我将其更改为“5 - MultiUse”并关闭项目以便在编译之前进行更新。我重新打开了项目,验证它仍然设置为“5 - MultiUse”,然后编译项目并干净地编译而没有错误消息。

当错误消息说它不允许引用私有对象时,该对象确实是私有的。一旦我宣布它不是私有的,并且项目模块接受了新的设置,它就会干净地编译。

答案 5 :(得分:0)

在模块中定义UDF(公共类型):

Public Type TPVArticulo
    Referencia As String
    Descripcion As String
    PVP As Double
    Dto As Double
End Type

并在课程中使用Friend,模块o frm:

Friend Function GetArticulo() As TPVArticulo

答案 6 :(得分:-4)

必须在公共对象中声明UDT,例如:

Public Class Sample

    Public Strucutre UDT
       Dim Value As Object
    End Structure

End Class