Tipo definito dall'utente (UDT) come parametro in pubblico Sub nel modulo di classe (VB6)

StackOverflow https://stackoverflow.com/questions/975982

  •  13-09-2019
  •  | 
  •  

Domanda

Ho cercato di risolvere questo problema, ma non riesco a trovare alcuna soluzione. Ho un UDT definito in un modulo normale, e volevo usarlo come parametro in un Public Sub in un modulo di classe. Allora ottengo un errore di compilazione:

  

definiti dall'utente Solo pubblica tipi definiti in moduli di oggetto pubbliche possono essere utilizzate come parametri o tipo restituito procedure pubbliche di moduli di classe o come campi di tipo definito dall'utente pubblici

Allora provo a spostare la mia UDT nella classe, dichiarata come Private. Ottengo questo errore di compilazione:

  

Enum privato e tipi definiti dall'utente non possono essere utilizzati come parametri o tornare tipi di procedure pubbliche, membri di dati pubblici, o campi di tipi definiti dall'utente pubblico.

I finaly cerco di dichiararla come Public nella classe, e ottengo questo errore di compilazione:

  

Non è possibile definire un tipo definito dall'utente pubblico all'interno di un modulo oggetto privato.

Quindi non v'è alcun modo per avere un UDT pubblico utilizzato come parametro in un sub pubblica in una classe?

È stato utile?

Soluzione

  

Quindi non v'è alcun modo per avere un pubblico   UDT utilizzata come parametro in un pubblico   sub in una classe?

In una parola, no. Il più vicino si può venire con il proprio codice Classic VB sarebbe quello di creare una classe che replica l'UDT e l'uso che, invece. Ci sono sicuramente vantaggi lì, ma sei hosed se è necessario passare che, per esempio, un'API pure.

Un'altra opzione è quella di definire l'UDT in una libreria dei tipi. Se lo fai, può essere utilizzato come parametro per un metodo pubblico.

Altri suggerimenti

Basta definire il sub come ambito Friend. Questo compila bene per me in una classe VB6.

Private Type testtype
  x As String
End Type


Friend Sub testmethod(y As testtype)

End Sub

Da vostri messaggi di errore compare la classe è privata. Se si desidera che la classe di essere pubblico - vale a dire che si stanno facendo un exe ActiveX o DLL e si desidera che i client siano in grado di accedere al sub -. Poi basta fare sia il tipo e la Public Sub

Ok, ecco come farlo, se posso ottenere il mio gatto di lasciarmi in pace, cioè.

In Form1 (con un pulsante di comando su di esso):

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 (senza controlli necessari). (Questo avrebbe potuto altrettanto facilmente stato un oggetto creato con una classe.):

    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

E infine, questo va in un file di modulo (BAS).

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

Basta passare l'UDT come parametro di riferimento e che funzionerà. :)

'method in the class

Public Sub CreateFile(ByRef udt1 As UdtTest)

End Sub

Ho avuto lo stesso messaggio di errore e dopo aver controllato l'applicazione, ho scoperto che nella finestra delle proprietà per la classe, l'impostazione "Instancing" è stato impostato su "1 - Private" per l'oggetto di riferimento. Ho cambiato in "5 - MultiUse" ed ho ottenuto lo stesso messaggio di errore. Allora sono andato indietro a una versione del modulo del progetto prima di quando ho aggiunto che fa riferimento all'oggetto e ha aggiunto che il progetto di nuovo - è in default a "1 - Private". Ho cambiato in "5 - MultiUse" prima di fare qualsiasi altra cosa e chiusi il progetto per poter aggiornare prima di compilare. I riaperto il progetto, si è verificato ancora impostato. "5 - MultiUse", poi compilato il progetto ed è compilato in modo pulito, senza il messaggio di errore

Quando il messaggio di errore è stato dicendo che non ha permesso riferimento a un oggetto privato, l'oggetto era veramente privata. Una volta ho dichiarato che non privata, e il modulo del progetto accettato questa nuova impostazione, è compilato in modo pulito.

Definisci UDF (tipo pubblico) in un modulo:

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

e utilizzare Friend in classe, il modulo o frm:

Friend Function GetArticulo() As TPVArticulo

L'UDT deve essere dichiarato in un oggetto pubblico, come:

Public Class Sample

    Public Strucutre UDT
       Dim Value As Object
    End Structure

End Class
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top