2009-06-10 51 views
14

我試圖解決這個問題,但找不到任何解決方案。我有一個在普通模塊中定義的UDT,並且希望將它用作類模塊中的Public Sub的參數。然後我得到一個編譯錯誤:用戶定義類型(UDT)作爲參數在公共Sub類模塊(VB6)

Only public user defined types defined in public object modules can be used as parameters or return type for public procedures of class modules or as fields of public user defined types

然後我試着將我的UDT的類,聲明爲Private。我得到這個編譯錯誤:

Private Enum and user defined types cannot be used as parameters or return types for public procedures, public data members, or fields of public user defined types.

我finaly嘗試將其申報爲類Public,並得到這個編譯錯誤:

Cannot define a Public user-defined type within a private object module.

那麼,有沒有辦法有用作公共UDT一個公共子類中的參數?

回答

9

So is there any way to have a public UDT used as a parameter in a public sub in a class?

總之,沒有。您可以使用經典的VB代碼最接近的就是創建一個複製UDT並使用它的類。這裏肯定有優點,但如果你需要將它傳遞給API,那麼你就會受到影響。

另一種選擇是在typelib中定義UDT。如果你這樣做,它可以用作公共方法的參數。

+3

我認爲我遲了一點,但是......我完全可以擁有一個公共UDT作爲參數我的Excel VBA應用程序中的公共子類(一類)。 – 2012-05-11 15:54:20

+1

我甚至遲到了,但是...... @安德烈·內維斯我確認我也可以。但是,根據我的發現,UDT的定義不能被封裝,這是一個可憐的事情。 – 2014-07-07 05:55:19

-3

的UDT必須在公用對象中聲明,如:

Public Class Sample 

    Public Strucutre UDT 
     Dim Value As Object 
    End Structure 

End Class 
+2

這是VB.NET,VB6不和你做班級公衆。如果項目是一個ActiveX exe或DLL,那麼只有在VB6中才有可能 - 即使提問者可能實際上並不希望公開該類。 – MarkJ 2009-06-10 15:14:22

16

只要定義子爲Friend範圍。這在VB6類中適合我。

Private Type testtype 
    x As String 
End Type 


Friend Sub testmethod(y As testtype) 

End Sub 

從您的錯誤消息看,你的班級是私人的。如果你想讓你的課程公開 - 即你正在製作一個ActiveX exe或DLL,並且你希望客戶端能夠訪問這個子課件,那麼只需製作這個類型和Sub Public。

+1

這應該被標記爲「正確答案」。 – 2016-05-06 22:42:46

+0

@MaikenRoskilde不是真的。 「朋友」解決方案在一般情況下不起作用。從UDT中創建一個類更加靈活:您可以擁有UDT類型的屬性等。 – 2017-02-24 17:24:47

6

好吧,如果我能讓我的貓留下我一個人,那麼這就是如何做到這一點。

在Form(上面有一個命令按鈕):

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 
' 
1

只需將UDT作爲參考參數傳遞即可使用。 :)

'method in the class 

Public Sub CreateFile(ByRef udt1 As UdtTest) 

End Sub 
1

我有同樣的錯誤信息,並檢查應用程序後,我發現,在類的屬性窗口,在「實例化」設置被設置爲「1 - 專用」引用的對象。我將它改爲「5 - MultiUse」,並得到相同的錯誤信息。然後,在我添加引用對象並再次添加項目之前,我又回到了項目模塊的一個版本 - 默認爲「1 - Private」。在做任何其他事情之前,我將它更改爲「5 - MultiUse」,並在編譯之前關閉項目以更新它。我重新打開了該項目,驗證它仍然被設置爲「5 - MultiUse」,然後編譯該項目,並且它乾淨地編譯而沒有錯誤消息。

當錯誤消息說它不允許引用私有對象時,該對象確實是私有的。一旦我宣佈它不是私人的,並且項目模塊接受了這個新設置,它會乾淨地編譯。

0

一個模塊中定義UDF(公共型):

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

,並在課堂上使用Friend,模塊ØFRM:

Friend Function GetArticulo() As TPVArticulo 
相關問題