Пользовательский тип (UDT) в качестве параметра в общедоступном вложенном модуле класса (VB6)

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

  •  13-09-2019
  •  | 
  •  

Вопрос

Я пытался решить эту проблему, но не смог найти никакого решения.У меня есть UDT, определенный в обычном модуле, и я хотел использовать его в качестве параметра в Public Sub в модуле класса.Затем я получаю сообщение об ошибке компиляции:

Только общедоступные пользовательские типы, определенные в модулях общедоступных объектов, могут использоваться в качестве параметров или возвращаемого типа для общедоступных процедур модулей классов или в качестве полей общедоступных пользовательских типов

Затем я пытаюсь переместить свой UDT в класс, объявленный как Private.Я получаю эту ошибку компиляции:

Частные перечисляемые и определяемые пользователем типы не могут использоваться в качестве параметров или возвращаемых типов для общедоступных процедур, общедоступных элементов данных или полей общедоступных пользовательских типов.

В конце концов, я пытаюсь объявить это как Public в классе и получаем эту ошибку компиляции:

Невозможно определить общедоступный пользовательский тип в модуле частного объекта.

Итак, есть ли какой-нибудь способ использовать public UDT в качестве параметра в public sub в классе?

Это было полезно?

Решение

Итак, есть ли какой-нибудь способ использовать public UDT в качестве параметра в public sub в классе?

Одним словом, нет.Самое близкое, что вы можете сделать с классическим кодом VB, - это создать класс, который реплицирует UDT, и использовать его вместо этого.В этом определенно есть преимущества, но вы попадаете в затруднительное положение, если вам нужно передать это, скажем, также и API.

Другой вариант - определить UDT в typelib.Если вы сделаете это, его можно будет использовать в качестве параметра для открытого метода.

Другие советы

Просто определите подпрограмму как Friend объем.Для меня это нормально компилируется в классе VB6.

Private Type testtype
  x As String
End Type


Friend Sub testmethod(y As testtype)

End Sub

Судя по вашим сообщениям об ошибках, ваш класс является частным.Если вы хотите, чтобы ваш класс был общедоступным, т.е.вы создаете ActiveX exe или DLL и хотите, чтобы клиенты могли получить доступ к подпрограмме - тогда просто сделайте и тип, и подпрограмму общедоступными.

Хорошо, вот как это сделать, если я смогу заставить кошку оставить меня в покое.

В форме 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

В форме2 (элементы управления не требуются).(С таким же успехом это мог бы быть объект, созданный с помощью класса.):

    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

У меня было такое же сообщение об ошибке, и после проверки приложения я обнаружил, что в окне свойств класса для параметра «Создание экземпляра» для объекта, на который ссылаются, установлено значение «1 — Частный».Я изменил его на «5 — MultiUse» и получил то же сообщение об ошибке.Затем я вернулся к версии модуля проекта до того, как добавил этот объект, на который ссылается, и снова добавил его в проект - по умолчанию он имел значение «1 — Частный».Я изменил его на «5 - MultiUse», прежде чем делать что-либо еще, и закрыл проект, чтобы он мог обновиться перед компиляцией.Я снова открыл проект, убедился, что для него по-прежнему установлено значение «5 — MultiUse», затем скомпилировал проект, и он скомпилировался чисто, без сообщения об ошибке.

Когда в сообщении об ошибке говорилось, что ссылка на частный объект запрещена, объект действительно был частным.Как только я объявил его не частным, и модуль проекта принял эту новую настройку, он скомпилировался без проблем.

Определите UDF (открытый тип) в модуле:

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

и использовать Friend в классе, модуль или от:

Friend Function GetArticulo() As TPVArticulo

UDT должен быть объявлен в публичном объекте, например:

Public Class Sample

    Public Strucutre UDT
       Dim Value As Object
    End Structure

End Class
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top