클래스 모듈 (VB6)에서 공개 서브의 매개 변수로서 UDT (User Defined Type)
-
13-09-2019 - |
문제
이 문제를 해결하려고했지만 해결책을 찾을 수 없습니다. UDT가 일반 모듈에 정의되어 있으며이를 매개 변수로 사용하고 싶었습니다. Public Sub
클래스 모듈에서. 그런 다음 컴파일 오류가 발생합니다.
공개 객체 모듈에 정의 된 공개 사용자 정의 유형 만 클래스 모듈의 공개 절차 또는 공개 사용자 정의 유형의 필드로 매개 변수 또는 반환 유형으로 사용할 수 있습니다.
그런 다음 수업에서 UDT를 옮기려고합니다. Private
. 이 컴파일 오류가 발생합니다.
개인 열거 및 사용자 정의 유형은 공개 절차, 공개 데이터 구성원 또는 공개 사용자 정의 유형의 분야에 대한 매개 변수 또는 반환 유형으로 사용할 수 없습니다.
마지막으로 선언하려고합니다 Public
클래스 에서이 컴파일 오류를 받으십시오.
개인 객체 모듈 내에서 공개 사용자 정의 유형을 정의 할 수 없습니다.
그렇다면 공개 UDT를 수업에서 공개 서브에서 매개 변수로 사용하는 방법이 있습니까?
해결책
그렇다면 공개 UDT를 수업에서 공개 서브에서 매개 변수로 사용하는 방법이 있습니까?
한마디로, 아니요. 클래식 VB 코드만으로 올 수있는 가장 가까운 것은 UDT를 복제하고 대신 사용하는 클래스를 만드는 것입니다. 여기에는 분명히 장점이 있지만 API도 전달해야한다면 호출됩니다.
또 다른 옵션은 Typelib에서 UDT를 정의하는 것입니다. 그렇게하면 공개 메소드의 매개 변수로 사용할 수 있습니다.
다른 팁
서브를 다음과 같이 정의하십시오 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
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- 비공개"로 설정되어 있음을 알았습니다. "5- 다중 사용"으로 변경하고 동일한 오류 메시지를 받았습니다. 그런 다음 참조 된 객체를 추가하고 프로젝트를 다시 추가하기 전에 프로젝트 모듈의 버전으로 돌아갔습니다. 다른 작업을 수행하기 전에 "5- 다중 사용"으로 변경하고 컴파일하기 전에 업데이트하도록 프로젝트를 닫았습니다. 프로젝트를 다시 열었고 여전히 "5- 멀티 사용"으로 설정되었다고 확인한 다음 프로젝트를 컴파일하고 오류 메시지없이 깨끗하게 컴파일했습니다.
오류 메시지가 개인 객체를 참조하는 것을 허용하지 않았다고 말할 때 객체는 실제로 비공개였습니다. 개인이 아니라고 선언하고 프로젝트 모듈은 새로운 설정을 받아 들였으며 깨끗하게 컴파일했습니다.
모듈에서 UDF (공개 유형) 정의 :
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