Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

User-Defined Types and Classes

10 views
Skip to first unread message

xytsrm

unread,
Sep 25, 2009, 1:19:01 PM9/25/09
to
Does anyone know if there's a way to declare a user-defined type as an
argument in a class method in VB6?

dpb

unread,
Sep 25, 2009, 1:58:10 PM9/25/09
to
xytsrm wrote:
> Does anyone know if there's a way to declare a user-defined type as an
> argument in a class method in VB6?

Unless this is a trick question, class methods are just functions as any
other...

--


Ralph

unread,
Sep 25, 2009, 2:24:42 PM9/25/09
to

"xytsrm" <xyt...@discussions.microsoft.com> wrote in message
news:EBE903F1-A74A-45CC...@microsoft.com...

> Does anyone know if there's a way to declare a user-defined type as an
> argument in a class method in VB6?
>

Make sure the UDT is declared Public and change the class method attribute
to 'Friend'.

However, UDTs are a tad probelmatic in VB, as the above will work in most
cases, but awkward in others.

To manage packaged variables/iemts more "universally" convert your UDTs to a
class, or define them in a type library.

"Converting a User Defined Type to a Class Module"
http://www.vbsight.com/UDT_Class.htm

"TypeLib tutorial"
http://www.devx.com/vb2themax/Article/19830/1763/page/1

"McKinney's WinAPI typelib download"
This package is useful as you can use and abuse his IDLs as examples for
creating your own.
http://vb.mvps.org/hardcore/html/sourcecode.htm
(download the WinTlbU.zip)

-ralph


xytsrm

unread,
Sep 25, 2009, 3:35:01 PM9/25/09
to
Hi Ralph,

You correctly recognize the problem is about "Scope".

In order for the UDF to be seen by the Class, I had to define it in the
Class. Unfortunately then it is not seen in the main program, and if defined
in the main program, its not available to the Class.

I was hoping to coerce the Class-method argument, declared as a Variant, but
when I define the UFD in the main, it produces the error:

"Only user-defined types defined in public object modules can be coerced to
or from a Variant or passed to late-bound functions"

That error suggests that the Variant could be coerced, if I could declare
the main module public, but I haven't figured out how to do that.

X.

xytsrm

unread,
Sep 25, 2009, 4:03:02 PM9/25/09
to
Hi Ralph,

I tried your suggestion of setting the UFD (in the Class) to Public, and
then setting the Class-method to "Friend". I still get to following error:

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

X.

xytsrm

unread,
Sep 25, 2009, 4:17:01 PM9/25/09
to
Hi Ralph,

I got it working. Apparently I missed a combination.

I created a separate standard-module for the main code; this allowed me to
declare the UDT as "Public" [with out getting the afore mentioned compilation
error], and that made it available to the Class-module.


Thanks for your help it's much appreciated!

X.

Eduardo

unread,
Sep 25, 2009, 4:55:55 PM9/25/09
to
xytsrm escribió:

> In order for the UDF to be seen by the Class, I had to define it in the
> Class. Unfortunately then it is not seen in the main program, and if defined
> in the main program, its not available to the Class.

1) You can define it in both projects or...
2) Define it in a class that its Instancing property is set to
GlobalMultiUse

> I was hoping to coerce the Class-method argument, declared as a Variant, but
> when I define the UFD in the main, it produces the error:
>
> "Only user-defined types defined in public object modules can be coerced to
> or from a Variant or passed to late-bound functions"

You can't just pass the UDT, but you can change from:

Public Function TheFunction (nMyUDT as MY_UDT) as Variant

to

Public Function TheFunction (nMyUDTPtr as Long) as Variant
Dim iMyUDT as MY_UDT

CopyMemoryRead iMyUDT, nMyUDTPtr, LenB(iMyUDT)
' You have teh UDT in iMyUDT

And you call The function:

Dim iReturnValue as Variant
Dim iMyUDTPtr as Long

' You need to have the UDT in mTheUDTHere
iMyUDTPtr = VarPtr (mTheUDTHere)
iReturnValue = TheFunction (iMyUDTPtr)

' API declaration:
Declare Sub CopyMemoryRead Lib "kernel32" Alias _
"RtlMoveMemory" (Destination As Any, ByVal _
Source As Long, ByVal Length As Long)

> That error suggests that the Variant could be coerced, if I could declare
> the main module public, but I haven't figured out how to do that.

I don't understand what the error is traying to say, but I think it's
not possible.

Eduardo

unread,
Sep 25, 2009, 4:58:25 PM9/25/09
to
xytsrm escribió:

> Hi Ralph,
>
> I got it working. Apparently I missed a combination.
>
> I created a separate standard-module for the main code; this allowed me to
> declare the UDT as "Public" [with out getting the afore mentioned compilation
> error], and that made it available to the Class-module.

But do you have all in the same project, or is this an issue of passing
the UDT from one project to another?

xytsrm

unread,
Sep 25, 2009, 5:31:01 PM9/25/09
to
It was all in the same project.

MikeD

unread,
Sep 25, 2009, 8:09:38 PM9/25/09
to

"xytsrm" <xyt...@discussions.microsoft.com> wrote in message
news:EBE903F1-A74A-45CC...@microsoft.com...

> Does anyone know if there's a way to declare a user-defined type as an
> argument in a class method in VB6?
>

Using UDTs in classes usually doesn't bode well and can be fraught with
problems.

The usual "best" solution is to convert the UDT to a class of its own.

--
Mike

Ralph

unread,
Sep 25, 2009, 11:28:56 PM9/25/09
to

"xytsrm" <xyt...@discussions.microsoft.com> wrote in message
news:2D2A8160-258C-4855...@microsoft.com...

> Hi Ralph,
>
> I got it working. Apparently I missed a combination.
>
> I created a separate standard-module for the main code; this allowed me to
> declare the UDT as "Public" [with out getting the afore mentioned
compilation
> error], and that made it available to the Class-module.
>

I should have been more clear of where to define the UDT. Perhaps I should
have used the term "Global". "Global" was essentially deprecated with the
introduction of Public/Private, but is still useful to describe items in bas
modules that you expect to be "in Scope" through out a project.

You have what you need now, but for completeness it should be noted that it
is possible to work with UDTs using a Variant. Here is one way to go about
that ...
http://www.brainbell.com/tutors/Visual_Basic/User_Defined_Types.htm

But pound for pound IMHO a typlib is the best way to go.

Also consider that a UDT by its very nature often forces a data-centric
solution. More often than not the association of various elements into a
single package to be treated as a single 'type' is in fact an object, thus
defining them as such leads to a better object-centric or object oriented
solution.

-ralph

Eduardo

unread,
Sep 26, 2009, 12:25:49 AM9/26/09
to
xytsrm escribió:

> It was all in the same project.

There is no problem then, you just need to declare the UDT in a module,
as public.

xytsrm

unread,
Sep 26, 2009, 8:04:01 PM9/26/09
to
Guys,

Many thanks for all your suggestions - I'm going to focus on converting the
UDT to a Class.

X.

xytsrm

unread,
Sep 27, 2009, 11:43:01 AM9/27/09
to
Ralph & MikeD,

It worked, instead of using a UDT I defined a simple class module with the
same data types as the UDT and it's visible to both the main program and
another class.

The only downside appears that for each, let's call it a virtual-UDT, I need
a separate class module - perhaps this is where Class-Collections might come
in handy.

X.

MikeD

unread,
Sep 27, 2009, 7:20:45 PM9/27/09
to

"xytsrm" <xyt...@discussions.microsoft.com> wrote in message

news:F26AE182-9E50-4FC0...@microsoft.com...


> Ralph & MikeD,
>
> It worked, instead of using a UDT I defined a simple class module with the
> same data types as the UDT and it's visible to both the main program and
> another class.
>
> The only downside appears that for each, let's call it a virtual-UDT, I
> need
> a separate class module - perhaps this is where Class-Collections might
> come
> in handy.
>

No, let's not call it a virtual-UDT. That'll just confuse things. It's a
class, so let's call it a class.

Not exactly sure what you mean. You can create as many instances of a class
as you wish. Typically, you use a collection if you create multiple
instances. Otherwise, you'd need to use distinct variables for each
instance.

If you were originally talking about 2 or more different UDTs, then yes,
you'd need a separate class module for each of those UDTs. But I don't see
how that's really any different. If you had 3 UDTs before, you'd simply
have 3 classes.

--
Mike


xytsrm

unread,
Sep 28, 2009, 10:55:01 AM9/28/09
to
Your right: I don't have very much experience with classes.
I created a property-only class (Class Q) and then tried to declare it like
this:

Dim X(5) As New Q

This did not cause any compilation or runtime errors: it actually appeared
to be working. However, after indexing data into what appeared to be an
array, I tried to retrieve it. It appears as though there was only a single
instance, because the first element was alway the last data to be entered.
From what you said it appears I need to create a collection if I want to
continue with this approach.

What I originally wanted to do is simply define a UDT and use it in the
main-code and a class module, but I ran into Scope issues with the UDT. I
beginning to think that Ralph's suggestion of creating a TypeLib may be the
easiest way to go.

The main reason I'm doing this is so I can return mulitple arguments from an
method and the UDT seemed the easiest way to go.

Your suggestions would be welcome.

X.

Ralph

unread,
Sep 28, 2009, 3:04:57 PM9/28/09
to

"xytsrm" <xyt...@discussions.microsoft.com> wrote in message
news:180F6825-0A67-44A8...@microsoft.com...

> Your right: I don't have very much experience with classes.
> I created a property-only class (Class Q) and then tried to declare it
like
> this:
>
> Dim X(5) As New Q
>
> This did not cause any compilation or runtime errors: it actually appeared
> to be working. However, after indexing data into what appeared to be an
> array, I tried to retrieve it. It appears as though there was only a
single
> instance, because the first element was alway the last data to be entered.
> From what you said it appears I need to create a collection if I want to
> continue with this approach.
>
> What I originally wanted to do is simply define a UDT and use it in the
> main-code and a class module, but I ran into Scope issues with the UDT. I
> beginning to think that Ralph's suggestion of creating a TypeLib may be
the
> easiest way to go.
>
> The main reason I'm doing this is so I can return mulitple arguments from
an
> method and the UDT seemed the easiest way to go.
>
> Your suggestions would be welcome.
>

UDTs are good for this and they are the primary reason structs are used in
WinAPI calls. But also consider that a method can handle an obscene number
of arguments and just passing them back as ByRef parameters is easy and just
as simple to code. e.g. ...

' Some UDT with 3 elements (3 to shorten the code)
Public Type JunkUDT
lElement As Long
sElement As String
r8Element As Double
Endy Type

' somewhere ....
Dim st As JunkUDT
Dim lng As Long
Dim str As String
Dim dbl As Double
' fetch the values
st = obj.JunkMethod()
' assign or work with the elements returned
lng = st.lElement
fnFoo st.sEment
compared to ...
' fetch the values
st = obj.JunkMethod(lng, str, dbl)
' assign or work with the elements returned
lng = lng
fnFoo str

-ralph


xytsrm

unread,
Sep 28, 2009, 8:08:02 PM9/28/09
to
Hi Ralph,

Exactly, this issue of UDT's and Classes seemed to be getting more complex
then it was worth. While I had hoped to just pass and entire structure back
an forth, I ended up just passing in the individual parameters ByRef. I
equated them to the internal structural elements; use the strucures
internally then equated them back out - not elegant, but it works.

X.

xytsrm

unread,
Sep 28, 2009, 10:40:01 PM9/28/09
to
Ralph,

I was looking over your code; I keep running into an error with the UDT as
you've implemented it.

If I define a UDT in some main-module, I can type a variable with it in a
class-module, or I can define the UDT in the class-module and type a variable
in the main module with it, but soon as I run the App I get an error saying
that "you can't have a public UDT in a private module"?

X.

Ralph

unread,
Sep 29, 2009, 12:18:21 AM9/29/09
to

"xytsrm" <xyt...@discussions.microsoft.com> wrote in message
news:0C4B64E8-3A32-4381...@microsoft.com...

> Ralph,
>
> I was looking over your code; I keep running into an error with the UDT as
> you've implemented it.
>
> If I define a UDT in some main-module, I can type a variable with it in a
> class-module, or I can define the UDT in the class-module and type a
variable
> in the main module with it, but soon as I run the App I get an error
saying
> that "you can't have a public UDT in a private module"?
>

ha, once again I did air code. The assumption was the UDT was 'globally
known'. Spoiled by all those years of using a TypeLibrary.

You are correct, you can't do my example without additional work as already
discussed. I was only pointing out, that often a UDT is considered a
'short-cut' when in fact simply providing a return parameter is just as
easy.

-ralph


xytsrm

unread,
Sep 29, 2009, 7:57:02 PM9/29/09
to
Ralph,

I'd like your opinion on the following: which of these approaches using a
file do you think would have the least overhead (i.e. run the fastest).

A. Creating a locked "Random" file, the records of which are added to and
over written by several apps, and periodically read by another app?

Or

B. Using a locked "Binary" file, that's wrtten to by several apps (created
on the first "open"), and then periodically read and killed, by another app?

X.

Ralph

unread,
Oct 7, 2009, 8:50:10 AM10/7/09
to

"xytsrm" <xyt...@discussions.microsoft.com> wrote in message
news:B3294915-9C12-483C...@microsoft.com...

> Ralph,
>
> I'd like your opinion on the following: which of these approaches using a
> file do you think would have the least overhead (i.e. run the fastest).
>
> A. Creating a locked "Random" file, the records of which are added to and
> over written by several apps, and periodically read by another app?
>
> Or
>
> B. Using a locked "Binary" file, that's wrtten to by several apps (created
> on the first "open"), and then periodically read and killed, by another
app?
>

This response is very late. (Didn't see the message until now for some
reason.) I'm very surprised someone didn't respond before now. As a week has
passed I assume you have come up with a solution. But here is my take on
using a file to share data.

In general you simply will have to try out various locking schemes for your
problem domain and see which works 'best' as there is no one 'best'
solution. Any "locking" scheme will carry with it a set of
assumptions/conditions and will fail when presented with a scenario where
those assumptions/conditions are not valid.

Historically 'sharing' a file was a bit difficult as most DOSs (used in the
generic sense) didn't 'share' files well and had a very clear view of
ownership, ie, you had to work to over come the 'default'. Over time DOSs
became more flexible and now the default is to share a file, and you have to
do a bit of work to make them 'un-shareable'. With 'shared' files the main
issue is that while data integrity is insured, concurrency never is.
Concurrency is easiest to manage using a 'GateKeeper' model, which in
implementation varies widely, essentially boils down to a single entry point
for any data exchange.

You can roll your own, but there are advantages to using existing
technologies. For example, INI files or databases.

-ralph


0 new messages