Results 1 to 9 of 9

Thread: [RESOLVED] UDT array in private Class

  1. #1

    Thread Starter
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Resolved [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.

  2. #2
    Fanatic Member
    Join Date
    Mar 2009
    Posts
    804

    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

  3. #3
    Fanatic Member
    Join Date
    Mar 2009
    Posts
    804

    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

  4. #4

    Thread Starter
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Re: UDT array in private Class

    Quote Originally Posted by VBClassicRocks View Post
    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?

  5. #5
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,601

    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.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  6. #6

    Thread Starter
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Re: UDT array in private Class

    Quote Originally Posted by Niya View Post
    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.

  7. #7
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,601

    Re: UDT array in private Class

    Quote Originally Posted by Jonney View Post
    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.

    Quote Originally Posted by Jonney View Post
    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.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  8. #8
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    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.

  9. #9

    Thread Starter
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Re: UDT array in private Class

    Quote Originally Posted by dilettante View Post
    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
  •  



Click Here to Expand Forum to Full Width