Определенный тип пользователей (УДТ) в качестве параметра в общественных Sub в модуле класса (в VB6)
Я пытался решить эту проблему, но не могу найти любое решение. У меня есть UDT, определенный в обычном модуле, и я хотел использовать его в качестве параметра в Public Sub
в модуле класса. Затем я получаю ошибку компиляции:
в качестве параметров или возвращаемого типа для общедоступных процедур модулей классов или полей общедоступных пользовательских типов могут использоваться только общедоступные пользовательские типы, определенные в модулях общедоступных объектов
затем я пытаюсь переместить свой UDT в классе, заявлена как Private
. Я получаю эту ошибку компиляции:
частные перечисления и определенные пользователем типы не могут использоваться в качестве параметров или возвращаемых типов для открытых процедур, элементов открытых данных или полей открытых пользовательских типов.
я, наконец, пытаюсь объявить его как Public
в классе и получить эту ошибку компиляции:
не удается определить открытый пользовательский тип в модуле частного объекта.
Так есть ли способ, чтобы используется ли открытый UDT в качестве параметра в общедоступном sub в классе?
7 ответов
Итак, есть ли способ иметь общественность UDT используется в качестве параметра в public Саба в классе?
словом, нет. Самое близкое, что вы можете сделать с классическим кодом VB, - это создать класс, который реплицирует UDT и использует его вместо этого. Там определенно есть преимущества, но вы обливаетесь, если вам нужно передать это, скажем, API.
другой вариант-определить UDT в typelib. Если вы это сделаете, его можно использовать как параметр для метода.
просто определите sub как Friend
объем. Это компилирует штраф для меня в классе VB6.
Private Type testtype
x As String
End Type
Friend Sub testmethod(y As testtype)
End Sub
из ваших сообщений об ошибках кажется, что ваш класс является частным. Если вы хотите, чтобы ваш класс был общедоступным-т. е. вы делаете ActiveX exe или DLL, и вы хотите, чтобы клиенты могли получить доступ к sub - тогда просто сделайте тип и sub общедоступными.
хорошо, вот как это сделать, если я могу заставить моего кота оставить меня в покое, то есть.
В 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
'
просто передайте UDT как ссылочный параметр, и он будет работать. :)
'method in the class
Public Sub CreateFile(ByRef udt1 As UdtTest)
End Sub
У меня было такое же сообщение об ошибке, и после проверки приложения я обнаружил, что в окне свойств для класса параметр "Instancing" был установлен в "1 - Private" для указанного объекта. Я изменил его на "5-MultiUse" и получил то же сообщение об ошибке. Затем я вернулся к версии модуля проекта до того, как я добавил этот ссылочный объект и добавил его снова в проект - он по умолчанию "1 - Private". Я изменил его на "5 - MultiUse", прежде чем делать что-либо еще и закрыл проект для его обновления перед компиляцией. Я снова открыл проект, проверил, что он все еще установлен на "5 - MultiUse", затем скомпилировал проект, и он был скомпилирован чисто без сообщения об ошибке.
когда сообщение об ошибке сообщало, что оно не позволяет ссылаться на частный объект, объект действительно был частным. Как только я объявил его не частным, и модуль проекта принял эту новую настройку, он был скомпилирован чисто.
определите UDF (public type) в модуле:
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
UDT должен быть объявлен в общедоступном объекте, например:
Public Class Sample
Public Strucutre UDT
Dim Value As Object
End Structure
End Class