cfi*_*her 16 vb6 vba user-defined-types
我试图解决这个问题,但找不到任何解决方案.我在普通模块中定义了UDT,并希望将其用作Public Sub
类模块中的参数.然后我得到一个编译错误:
只有公共对象模块中定义的公共用户定义类型可以用作类模块的公共过程的参数或返回类型,或者用作公共用户定义类型的字段
然后我尝试在类中移动我的UDT,声明为Private
.我得到这个编译错误:
私有枚举和用户定义的类型不能用作公共过程,公共数据成员或公共用户定义类型字段的参数或返回类型.
我最终尝试Public
在类中声明它,并得到此编译错误:
无法在私有对象模块中定义公共用户定义的类型.
那么有没有办法让公共UDT用作类中公共子的参数?
Mar*_*rkJ 18
只需将sub定义为Friend
范围即可.这对VB6类的编译很好.
Private Type testtype
x As String
End Type
Friend Sub testmethod(y As testtype)
End Sub
Run Code Online (Sandbox Code Playgroud)
从您的错误消息中可以看出您的课程是私密的.如果您确实希望您的类是公共的 - 即您正在创建ActiveX exe或DLL并且您希望客户端能够访问该子类 - 那么只需要创建类型和子公共.
Kar*_*son 10
那么有没有办法让公共UDT用作类中公共子的参数?
总之,没有.您可以使用Classic VB代码最接近的是创建一个复制UDT并使用它的类.这里肯定有优势,但是如果你需要将它传递给API,那么你就会受到冲击.
另一种选择是在类型库中定义UDT.如果这样做,它可以用作公共方法的参数.
小智 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
Run Code Online (Sandbox Code Playgroud)
在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
Run Code Online (Sandbox Code Playgroud)
最后,这是一个模块(BAS)文件.
Option Explicit
'
' This is just the UDT that is used for the example.
Public Type MyUdtType
l As Long
End Type
'
Run Code Online (Sandbox Code Playgroud)