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

后端 未结 7 1163
感动是毒
感动是毒 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: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
    '
    

提交回复
热议问题