-
Jul 2nd, 2014, 04:19 AM
#1
Thread Starter
Frenzied Member
[RESOLVED] UDT array in private Class
Actually, the error is very famous.
"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"
This error occurs when I access UDT array from another private class in standard exe project.
Code:
'in Class cECISet
Private Type QRECINameValue 'vb6 not allow to declare Public in private class
QR_ECI_Name As String
QR_ECI_Value As Long
End Type
Private m_tECIList() As QRECINameValue
'export array m_tECIList()
Public Property Get ECIListItem(ByVal index As Long) As QRECINameValue
ECIListItem = m_tECIList(index)
End Property
Private Sub Class_Initialize()
m_tECIList(0).QR_ECI_Name = "CP437"
m_tECIList(0).QR_ECI_Value=0
m_tECIList(1).QR_ECI_Name = "iso-8859-1"
m_tECIList(1).QR_ECI_Value=1
m_tECIList(2).QR_ECI_Name = "UTF-8"
m_tECIList(2).QR_ECI_Value=26
End Sub
I have to change Public Property to Friend Property and also,declare the same UDT in my Form1:
Code:
'In cECISet class
Friend Property Get ECIListItem(ByVal index As Long) As QRECINameValue
'In Form1
Private Type QRECINameValue
QR_ECI_Name As String
QR_ECI_Value As Long
End Type
Private Sub Form_Load()
Dim objECI As New cECISet
Debug.Print objECI.ECIListItem(2).QR_ECI_Name
End Sub
I want to retrieve whole array at one time instead of get individual item by index. What is modem way to solve the kind of problem,Copymemory or ObjectFromPtr?
Last edited by Jonney; Jul 2nd, 2014 at 06:14 AM.
-
Jul 2nd, 2014, 06:59 AM
#2
Re: UDT array in private Class
Change the class property from public to friend
Then in the form code
Code:
Private Sub Form_Load()
Dim objECI As New cECISet
Dim ECI As QRECINameValue
' Debug.Print objECI.ECIListItem(2).QR_ECI_Name
ECI = objECI.ECIListItem(2)
Debug.Print ECI.QR_ECI_Name, ECI.QR_ECI_Value
End Sub
-
Jul 2nd, 2014, 07:04 AM
#3
Re: UDT array in private Class
Of course you could add a module and declare the type structure
as public, avoiding the duplication.
Also, it is good practice to
Dim objECI as cECISet
set objECI = New cECISet
-
Jul 2nd, 2014, 08:19 AM
#4
Thread Starter
Frenzied Member
Re: UDT array in private Class
Originally Posted by VBClassicRocks
Of course you could add a module and declare the type structure
as public, avoiding the duplication.
yes. You are right.
Also, it is good practice to
Dim objECI as cECISet
set objECI = New cECISet
OK,sir.
Code:
Public Function getECIList(buffer() As QRECINameValue)
buffer = m_tECIList
End Function
Public Function doesn't work. Any work around?
-
Jul 2nd, 2014, 08:21 AM
#5
Re: UDT array in private Class
If I remembered correctly, this limitation has something to do with COM. The VB compiler can export public class modules as COM classes yet it doesn't or cannot map VB6's UDT's to an appropriate COM type which is why you can only use them privately.
In my last days of using VB6 I had actually begun to abandon using UDTs in favor of class modules for this very reason. I suggest you do the same. UDTs are a hold over from QuickBasic where I picked up the habit of using them in the first place. They were good for a primitive language like QuickBasic but in this modern era of objects and interfaces, they don't really have a place. You should try to stop using them especially if you're in the habit of writing libraries that export lots of classes with complex parameters. UDTs are only going to frustrate you. Use them if you need to interact with the Win32 API as they are compatible with C/C++ structs.
-
Jul 2nd, 2014, 08:26 AM
#6
Thread Starter
Frenzied Member
Re: UDT array in private Class
Originally Posted by Niya
If I remembered correctly, this limitation has something to do with COM. The VB compiler can export public class modules as COM classes yet it doesn't or cannot map VB6's UDT's to an appropriate COM type which is why you can only use them privately.
In my last days of using VB6 I had actually begun to abandon using UDTs in favor of class modules for this very reason. I suggest you do the same. UDTs are a hold over from QuickBasic where I picked up the habit of using them in the first place. They were good for a primitive language like QuickBasic but in this modern era of objects and interfaces, they don't really have a place. You should try to stop using them especially if you're in the habit of writing libraries that export lots of classes with complex parameters. UDTs are only going to frustrate you. Use them if you need to interact with the Win32 API as they are compatible with C/C++ structs.
I don't have knowledge on COM, but I agree with you as Dilettante also said. My concern is that if project has so many UDTs, I have to add the same amount of Classes, the project look mess. And, UDTs can be easy to save into file but hard for class.
-
Jul 2nd, 2014, 08:55 AM
#7
Re: UDT array in private Class
Originally Posted by Jonney
My concern is that if project has so many UDTs, I have to add the same amount of Classes, the project look mess.
Well for such projects, hopefully the vast majority are used internally so you should be spending minimal time converting only the few you want to expose via public properties in class modules. In my own experience, I've only ever needed to expose a few complex types in larger projects.
Originally Posted by Jonney
And, UDTs can be easy to save into file but hard for class.
Again, if these UDTs aren't meant to be exposed, you can leave them as UDTs. If you want to publicly expose UDTs that you intend to use as a data structure for a file then what you can do is create it as a private UDT within the class module that reflects the fields/properties that you want to save and use that UDT when serializing the class. It would require a lot of boilerplate to pass values back and forth especially if you have many fields/properties but its as clean a solution as I can think of.
Alternatively, I remember VB6 or COM having a class called a PropertyBag which facilitated persistence of class data but to be honest, I've only ever used them when authoring custom controls. I've never tried to use it on ordinary class modules. I'm not even sure it can be done. I can't seem to find any articles on a way to control where and how the PropertyBag persists its data. I suspect Dilettante or Schmidt might know more about this than I do.
Last edited by Niya; Jul 2nd, 2014 at 09:01 AM.
-
Jul 2nd, 2014, 10:01 AM
#8
Re: UDT array in private Class
You only have a few practical options.
First you can duplicate the Private UDT definitions and make a Friend Property.
Code:
Friend Property Get ECIList() As QRECINameValue()
ECIList = m_tECIList
End Property
Second you can create the required type information, which lets you get ride of those Private UDT definitions and change the property to Public. There are two ways to do this. Define the UDT's type information by: compiling an VB6 ActiveX DLL, compiling a TLB from IDL defining your UDT. Then set a reference to the DLL or TLB.
The property can now look like:
Code:
Public Property Get ECIList() As QRECINameValue()
ECIList = m_tECIList
End Property
CopyMemory isn't going to be much help because any dynamic String or array members of the UDT are not stored inline, and instead a pointer gets stored in the base struct and the dynamic item "hangs off" that. A UDT written to a random file isn't the same as the UDT's layout in memory.
-
Jul 2nd, 2014, 10:13 AM
#9
Thread Starter
Frenzied Member
Re: UDT array in private Class
Originally Posted by dilettante
You only have a few practical options.
First you can duplicate the Private UDT definitions and make a Friend Property.
Code:
Friend Property Get ECIList() As QRECINameValue()
ECIList = m_tECIList
End Property
Second you can create the required type information, which lets you get ride of those Private UDT definitions and change the property to Public. There are two ways to do this. Define the UDT's type information by: compiling an VB6 ActiveX DLL, compiling a TLB from IDL defining your UDT. Then set a reference to the DLL or TLB.
The property can now look like:
Code:
Public Property Get ECIList() As QRECINameValue()
ECIList = m_tECIList
End Property
CopyMemory isn't going to be much help because any dynamic String or array members of the UDT are not stored inline, and instead a pointer gets stored in the base struct and the dynamic item "hangs off" that. A UDT written to a random file isn't the same as the UDT's layout in memory.
I will go for option 1. It is easy.
Thank you,sir.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|