User Defined Type (UDT) as parameter in public Sub in class module (VB6)

后端 未结 7 1052
感动是毒
感动是毒 2020-12-04 22:41

I\'ve tried to solve this problem, but can\'t find any solution. I have a UDT defined in a normal module, and wanted to use it as parameter in a Public Sub in a

相关标签:
7条回答
  • 2020-12-04 23:18

    Define UDF (public type) in a module:

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

    and use Friend in class, module o frm:

    Friend Function GetArticulo() As TPVArticulo
    
    0 讨论(0)
  • 2020-12-04 23:27

    I had the same error message and after checking the application, I found that in the property window for the class, the "Instancing" setting was set to "1 - Private" for the referenced object. I changed it to "5 - MultiUse" and got the same error message. I then went back to a version of the project module prior to when I added that referenced object and added it again the project - it defaulted to "1 - Private". I changed it to "5 - MultiUse" before doing anything else and closed the project to for it to update before compiling. I re-opened the project, verified it was still set to "5 - MultiUse", then compiled the project and it compiled cleanly without the error message.

    When the error message was saying it didn't allow referencing a private object, the object really was private. Once I declared it not private, and the project module accepted that new setting, it compiled cleanly.

    0 讨论(0)
  • 2020-12-04 23:32

    Ok, here's how to do it, if I can get my cat to leave me alone, that is.

    In Form1 (with one command button on it):

    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
    

    In form2 (no controls needed). (This could have just as easily been an object created with a class.):

        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
    

    And Finally, this goes in a module (BAS) file.

        Option Explicit
    '
    ' This is just the UDT that is used for the example.
    Public Type MyUdtType
        l As Long
    End Type
    '
    
    0 讨论(0)
  • 2020-12-04 23:39

    The UDT must be declared in a Public Object, like:

    Public Class Sample
    
        Public Strucutre UDT
           Dim Value As Object
        End Structure
    
    End Class
    
    0 讨论(0)
  • 2020-12-04 23:43

    So is there any way to have a public UDT used as a parameter in a public sub in a class?

    In a word, no. The closest you can come with just Classic VB code would be to create a class that replicates the UDT and use that instead. There are definitely advantages there, but you're hosed if you need to pass that to, say, an API as well.

    Another option is to define the UDT in a typelib. If you do that, it can be used as a parameter for a public method.

    0 讨论(0)
  • 2020-12-04 23:44

    Just Pass the UDT as Reference parametre and it will work. :)

    'method in the class
    
    Public Sub CreateFile(ByRef udt1 As UdtTest)
    
    End Sub
    
    0 讨论(0)
提交回复
热议问题