Passing Components as Properties 
Author Message
 Passing Components as Properties

Hi,

I am new ATL and COM so bare with me if this is a little simple.

I am using VC++ 6.0 and I have created an ATL project.
I have several components in the project which I have automation
working for no problem.  Now I want to use some of these components as
properties of others.

IE.
I have two class interfaces an IParent and ISub - I can see both class
and there interface from my VB test app.

class ATL_NO_VTABLE CParent :
        public CComObjectRootEx<CComSingleThreadModel>,
        public CComCoClass<CParent1, &CLSID_Parent1>,
        public IDispatchImpl<IParent1, &IID_IParent1, &LIBID_BLLTESTLib>
.
.
.

CSub m_sub;

class ATL_NO_VTABLE CSub :
        public CComObjectRootEx<CComSingleThreadModel>,
        public CComCoClass<CSubUnit1, &CLSID_SubUnit1>,
        public IDispatchImpl<ISubUnit1,&IID_ISubUnit1,&LIBID_BLLTESTLib>

Now I want to add ISub as a property to IParent.  So that in VB I can
call something like.

Dim parent As Parent
parent.sub.DoSomeThing

I am not sure how to add the CSub property to CParent.
I added a new property to IParent as VARIANT.
But when I try to add CSub as a member to CParent I get a message
indicating I cannot instantiate abstract class due to following members
CSub m_sub;

Can anyone help me with this or can annyone point me to a good example
for this.

Thanks in advance,

ML

I have a several component in my

Sent via Deja.com
http://www.*-*-*.com/



Wed, 23 Jul 2003 04:43:08 GMT  
 Passing Components as Properties
You should return an interface pointer - not a C++ class. To create
an instance of the other class, you either use CoCreateInstance, or
create an internal instance via CComObject<> and friends. If the
property needs to be created along with your main class, consider
making it a member of your class. ATL doesn't provide a standard
template for sharing the reference count, so you'll have to write
one yourself. Something like this:

template <typename Base, typename Container>
class CComObjectNest : public Base
{
public:
    CComObjectNest(Container *pContainer)
    {
        m_pContainer = pContainer;
    }

    STDMETHOD(QueryInterface)(...)
    {
        // Copy it from CComObject
    }

    STDMETHOD_(ULONG, AddRef)();
    {
        return m_pContainer->GetUnknown()->AddRef();
    }

    STDMETHOD_(ULONG, Release)();
    {
        return m_pContainer->GetUnknown()->Release();
    }

protected:
    Conatiner *m_pContainer;

Quote:
};

You use it like this:

class ATL_NO_VTABLE CContainer :
    public CComObjectRootEx<...>,
    ...
{
public:
    CContainer() :
        m_Nested(this)
    {
    }
    ...

protected:
    CComObjectNest<CSub, CContainer> m_Nested;

Quote:
};

I just wrote this on the spot. You may have to tweak it a bit in order
to compile, but you get the idea...

When you want to return an interface pointer on the contained
object, you do:

hr = m_Nested.GetUnknown()->QueryInterface(IID_IWhatever,
                (void**)ppRetval);

This will bump up your own reference count so as to keep your
container object alive while the contained object is used. BTW,
this template doesn't give your CSub object a pointer to its
container - it is completely oblivious to the fact it is being
contained.

--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD

MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================

Quote:

> Hi,

> I am new ATL and COM so bare with me if this is a little simple.

> I am using VC++ 6.0 and I have created an ATL project.
> I have several components in the project which I have automation
> working for no problem.  Now I want to use some of these components as
> properties of others.

> IE.
> I have two class interfaces an IParent and ISub - I can see both class
> and there interface from my VB test app.

> class ATL_NO_VTABLE CParent :
> public CComObjectRootEx<CComSingleThreadModel>,
> public CComCoClass<CParent1, &CLSID_Parent1>,
> public IDispatchImpl<IParent1, &IID_IParent1, &LIBID_BLLTESTLib>
> .
> .
> .

> CSub m_sub;

> class ATL_NO_VTABLE CSub :
> public CComObjectRootEx<CComSingleThreadModel>,
> public CComCoClass<CSubUnit1, &CLSID_SubUnit1>,
> public IDispatchImpl<ISubUnit1,&IID_ISubUnit1,&LIBID_BLLTESTLib>

> Now I want to add ISub as a property to IParent.  So that in VB I can
> call something like.

> Dim parent As Parent
> parent.sub.DoSomeThing

> I am not sure how to add the CSub property to CParent.
> I added a new property to IParent as VARIANT.
> But when I try to add CSub as a member to CParent I get a message
> indicating I cannot instantiate abstract class due to following members
> CSub m_sub;

> Can anyone help me with this or can annyone point me to a good example
> for this.

> Thanks in advance,

> ML

> I have a several component in my

> Sent via Deja.com
> http://www.deja.com/



Wed, 23 Jul 2003 07:08:54 GMT  
 Passing Components as Properties
Thanks for the feed back.  I have tried to get this to work and I am
still struggling with it.  Do you know of any samples which implement
this?

If I want to use CoCreateInstance - how do I get IID I need?

I added
class __declspec(uuid("98BE3D23-1136-4245-B6EE-6F623486BEC0"))CSub1;
To the header file for the Sub component but I still cannot see it from
VB.

STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject)
{
      return _InternalQueryInterface(iid, ppvObject);

Quote:
}

I also changed the container class from
CComObjectNest<CSub, CContainer> m_Nested;
to
CComObjectNest<CSub, CContainer>* m_Nested;
Then I use CoCreateInstance.

Am I close or am I complete lost here?  Any help is greatly appreciated.

Thank You,

ML



Quote:
> You should return an interface pointer - not a C++ class. To create
> an instance of the other class, you either use CoCreateInstance, or
> create an internal instance via CComObject<> and friends. If the
> property needs to be created along with your main class, consider
> making it a member of your class. ATL doesn't provide a standard
> template for sharing the reference count, so you'll have to write
> one yourself. Something like this:

> template <typename Base, typename Container>
> class CComObjectNest : public Base
> {
> public:
>     CComObjectNest(Container *pContainer)
>     {
>         m_pContainer = pContainer;
>     }

>     STDMETHOD(QueryInterface)(...)
>     {
>         // Copy it from CComObject
>     }

>     STDMETHOD_(ULONG, AddRef)();
>     {
>         return m_pContainer->GetUnknown()->AddRef();
>     }

>     STDMETHOD_(ULONG, Release)();
>     {
>         return m_pContainer->GetUnknown()->Release();
>     }

> protected:
>     Conatiner *m_pContainer;
> };

> You use it like this:

> class ATL_NO_VTABLE CContainer :
>     public CComObjectRootEx<...>,
>     ...
> {
> public:
>     CContainer() :
>         m_Nested(this)
>     {
>     }
>     ...

> protected:
>     CComObjectNest<CSub, CContainer> m_Nested;
> };

> I just wrote this on the spot. You may have to tweak it a bit in order
> to compile, but you get the idea...

> When you want to return an interface pointer on the contained
> object, you do:

> hr = m_Nested.GetUnknown()->QueryInterface(IID_IWhatever,
>                 (void**)ppRetval);

> This will bump up your own reference count so as to keep your
> container object alive while the contained object is used. BTW,
> this template doesn't give your CSub object a pointer to its
> container - it is completely oblivious to the fact it is being
> contained.

> --
> =====================================
> Alexander Nickolov
> Microsoft MVP [VC], MCSD

> MVP VC FAQ: http://www.mvps.org/vcfaq
> =====================================




- Show quoted text -

Quote:
> > Hi,

> > I am new ATL and COM so bare with me if this is a little simple.

> > I am using VC++ 6.0 and I have created an ATL project.
> > I have several components in the project which I have automation
> > working for no problem.  Now I want to use some of these components
as
> > properties of others.

> > IE.
> > I have two class interfaces an IParent and ISub - I can see both
class
> > and there interface from my VB test app.

> > class ATL_NO_VTABLE CParent :
> > public CComObjectRootEx<CComSingleThreadModel>,
> > public CComCoClass<CParent1, &CLSID_Parent1>,
> > public IDispatchImpl<IParent1, &IID_IParent1, &LIBID_BLLTESTLib>
> > .
> > .
> > .

> > CSub m_sub;

> > class ATL_NO_VTABLE CSub :
> > public CComObjectRootEx<CComSingleThreadModel>,
> > public CComCoClass<CSubUnit1, &CLSID_SubUnit1>,
> > public IDispatchImpl<ISubUnit1,&IID_ISubUnit1,&LIBID_BLLTESTLib>

> > Now I want to add ISub as a property to IParent.  So that in VB I
can
> > call something like.

> > Dim parent As Parent
> > parent.sub.DoSomeThing

> > I am not sure how to add the CSub property to CParent.
> > I added a new property to IParent as VARIANT.
> > But when I try to add CSub as a member to CParent I get a message
> > indicating I cannot instantiate abstract class due to following
members
> > CSub m_sub;

> > Can anyone help me with this or can annyone point me to a good
example
> > for this.

> > Thanks in advance,

> > ML

> > I have a several component in my

> > Sent via Deja.com
> > http://www.deja.com/

Sent via Deja.com
http://www.deja.com/


Sat, 26 Jul 2003 07:24:06 GMT  
 Passing Components as Properties
Oh, you're completely off topic :)... You should do:

class CContainer :
    public CComObjectRootEx<...>,
    ...
{
    CContainer() : m_Sub(this)
    {
    }
    ...
protected:
    CComObjectNest<CSub, CContainer> m_Sub;

Quote:
}

When you have to return the inner object:

STDMETHODIMP CContainer::get_Inner(IDispatch **ppVal)
{
    return m_Sub.GetUnknwon()->QueryInterface(
            IID_IDispatch, (void**)ppVal);

Quote:
}

There's no CoCreateInstance invloved whatsoever!

The one thing I'm not sure about is whether you can pass your
this pointer when initializing the member variable. If not, use
a default constructor and an initialization method instead.

--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD

MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================

Quote:

> Thanks for the feed back.  I have tried to get this to work and I am
> still struggling with it.  Do you know of any samples which implement
> this?

> If I want to use CoCreateInstance - how do I get IID I need?

> I added
> class __declspec(uuid("98BE3D23-1136-4245-B6EE-6F623486BEC0"))CSub1;
> To the header file for the Sub component but I still cannot see it from
> VB.

> STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject)
> {
>       return _InternalQueryInterface(iid, ppvObject);
> }

> I also changed the container class from
> CComObjectNest<CSub, CContainer> m_Nested;
> to
> CComObjectNest<CSub, CContainer>* m_Nested;
> Then I use CoCreateInstance.

> Am I close or am I complete lost here?  Any help is greatly appreciated.

> Thank You,

> ML



> > You should return an interface pointer - not a C++ class. To create
> > an instance of the other class, you either use CoCreateInstance, or
> > create an internal instance via CComObject<> and friends. If the
> > property needs to be created along with your main class, consider
> > making it a member of your class. ATL doesn't provide a standard
> > template for sharing the reference count, so you'll have to write
> > one yourself. Something like this:

> > template <typename Base, typename Container>
> > class CComObjectNest : public Base
> > {
> > public:
> >     CComObjectNest(Container *pContainer)
> >     {
> >         m_pContainer = pContainer;
> >     }

> >     STDMETHOD(QueryInterface)(...)
> >     {
> >         // Copy it from CComObject
> >     }

> >     STDMETHOD_(ULONG, AddRef)();
> >     {
> >         return m_pContainer->GetUnknown()->AddRef();
> >     }

> >     STDMETHOD_(ULONG, Release)();
> >     {
> >         return m_pContainer->GetUnknown()->Release();
> >     }

> > protected:
> >     Conatiner *m_pContainer;
> > };

> > You use it like this:

> > class ATL_NO_VTABLE CContainer :
> >     public CComObjectRootEx<...>,
> >     ...
> > {
> > public:
> >     CContainer() :
> >         m_Nested(this)
> >     {
> >     }
> >     ...

> > protected:
> >     CComObjectNest<CSub, CContainer> m_Nested;
> > };

> > I just wrote this on the spot. You may have to tweak it a bit in order
> > to compile, but you get the idea...

> > When you want to return an interface pointer on the contained
> > object, you do:

> > hr = m_Nested.GetUnknown()->QueryInterface(IID_IWhatever,
> >                 (void**)ppRetval);

> > This will bump up your own reference count so as to keep your
> > container object alive while the contained object is used. BTW,
> > this template doesn't give your CSub object a pointer to its
> > container - it is completely oblivious to the fact it is being
> > contained.

> > --
> > =====================================
> > Alexander Nickolov
> > Microsoft MVP [VC], MCSD

> > MVP VC FAQ: http://www.mvps.org/vcfaq
> > =====================================



> > > Hi,

> > > I am new ATL and COM so bare with me if this is a little simple.

> > > I am using VC++ 6.0 and I have created an ATL project.
> > > I have several components in the project which I have automation
> > > working for no problem.  Now I want to use some of these components
> as
> > > properties of others.

> > > IE.
> > > I have two class interfaces an IParent and ISub - I can see both
> class
> > > and there interface from my VB test app.

> > > class ATL_NO_VTABLE CParent :
> > > public CComObjectRootEx<CComSingleThreadModel>,
> > > public CComCoClass<CParent1, &CLSID_Parent1>,
> > > public IDispatchImpl<IParent1, &IID_IParent1, &LIBID_BLLTESTLib>
> > > .
> > > .
> > > .

> > > CSub m_sub;

> > > class ATL_NO_VTABLE CSub :
> > > public CComObjectRootEx<CComSingleThreadModel>,
> > > public CComCoClass<CSubUnit1, &CLSID_SubUnit1>,
> > > public IDispatchImpl<ISubUnit1,&IID_ISubUnit1,&LIBID_BLLTESTLib>

> > > Now I want to add ISub as a property to IParent.  So that in VB I
> can
> > > call something like.

> > > Dim parent As Parent
> > > parent.sub.DoSomeThing

> > > I am not sure how to add the CSub property to CParent.
> > > I added a new property to IParent as VARIANT.
> > > But when I try to add CSub as a member to CParent I get a message
> > > indicating I cannot instantiate abstract class due to following
> members
> > > CSub m_sub;

> > > Can anyone help me with this or can annyone point me to a good
> example
> > > for this.

> > > Thanks in advance,

> > > ML

> > > I have a several component in my

> > > Sent via Deja.com
> > > http://www.deja.com/

> Sent via Deja.com
> http://www.deja.com/



Mon, 28 Jul 2003 08:32:27 GMT  
 
 [ 4 post ] 

 Relevant Pages 

1. Passing SmartPtr through two components

2. Passing a 2D SafeArray from VB client to ATL COM component

3. How to pass an ADODB.Stream object from VB to a method in a C++ component

4. How to pass vb Object into ATL component

5. Passing an HICON from component

6. Passing a component instance to another object

7. Passing component pointer from atl service to vb

8. Passing array of string to component

9. passing strings from ATL component to VB app

10. Passing an external ADO connection into an MTS component

11. Passing Object to DCOM component

12. Passing DOMDocuments in/out of com components

 

 
Powered by phpBB® Forum Software