vc++ 6.0

I have defined some class properties or methods of myselves in an MFC ActiveX . But I can't use it in VB.
For example, I defined two classes named CPoint and CPoints use MFC class wizard as follow:
  class CPoint : public CCmdTarget
     X : double;
     Y : double;
     ...(methods and properties)

  class CPoints : public CCmdTarget
     CPoint Items(short Index);
     void Add(CPoint aPoint);
     ...(methods and properties)
   class CMyActiveXCtl : public COleControl

   Now I suppose that I will use these two ActiveX Automation objects in VB 6.0 as follow:
   dim pt as new Point
   dim pts as new Points
   pt.x = 100.1
   pt.y = 200.1
   May you tell me how can I realize these? If possible, please give me the actual steps and detail source code of the example.Thanks a lot.

Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Use ATL in VC++.

1.  Create  a project in VC++ as an ATL project, choose DLL or ACTIVEX/CLIENT
2. use  Insert->New ATL Object to create a new ATL object (choose Simple Object)
3. right-click on the MIDL extension objject and add a property.
4 write the code for that property
5. compile the OCX
6. Use the OCX in VB
7. Done

Look on Microsofts web site on in MSDN for ATL tutorial and follow that.


Use MFC in VC++

1. Create a new project - Choose MFC AppWizard (dll)
2. In first AppWizard dialog window,
    Select 'Automation' checkbox to enable Automation
3.  Click Finish..Ok to complete the creation of the
    skeleton application
4.  Using ClassWizard, create a new class derived from
    CCmdTarget. Name this class 'Point'. Select 'Creatable by
    Type ID' checkbox and specify the name you want to use
    under Visual Basic.  (e.g. MyApp.Point)
5.  In ClassWizard, select the Automation tab for the Point
    class and add the Properties and methods you need.  
    This gives you a correctly structured class with skeleton
    version of the properties you specified.(Specify the type of
    your x/y properties as float or double if you intend to
    use decimal points as in your example code above.)
6.  Now go to the code file and add any functionality that takes
    care of storing/retrieving the property value during a
    Get/Set call, etc.
7.  Follow the same for the 'Points' class.  You will need to
    implement some kind of collection to hold the items you add.
    The CPtrList is a good way to hold them.
8.  Once you get the skeleton methods fleshed out, you can test
    this from VB using code like what you specified above.

9.  Because these are Automation objects, you must use their
    AddRef() and Release() methods to signal your interest in
    them. Review the IUnknown::AddRef() and IUnknown::Release()
    documentation from MSVC.


All the Automation objects you creat are represented by LPDISPATCH type pointers.  When you add the function Add() to the Points class, you should specify a parameter of type LPDISPATCH for the method.  You should see something like this
in the Points.h header file:

      // Generated OLE dispatch map functions
      afx_msg void Add(LPDISPATCH item);

When you go back to the Points.cpp file, you'll see this:
(I've added my own comment)
// Points message handlers

void Points::Add(LPDISPATCH item)
      // TODO: Add your dispatch handler code here
      /* Here you implement the code that accepts and
      *  manages the LPDISPATCH pointer
      *  For example, using a CPtrList:
      *  m_List.AddTail(item);

In the Points::Add method, you'll need to write code to manage the collection of LPDISPATCH pointers you'll be receiving via the Add() method. The CPtrList member mentioned above would be
part of the Points class and initialized in the constructor. Add
it yourself, since it is a C++ only member, never accessed via
Automation by VB.


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
AxyAuthor Commented:
Sir, thanks very for your help, I have found another method to resolve the question, that is to use the FromIDispatch() and GetIDispatch(), I felt it is more convenient than the method you give me, do you think so? In another hand, if you can tell me how can I define an array property in VC? For example, Item is an arrry proerty of Points, and I will use it in VB as following:
                   Dim pts as new Points
                   Dim p as new Point
                   pts.add p
                   Dim p1 as new Point
                   set p1 = pts(0)

Note: the Item is an default property of points in VC++.
How can I define _NewEnum proeperty in class Points?

The LPDISPATCH pointer you get is equivalent to the pointer you get from calling GetIDispatch, no difference.  When you call Points.Add from VB, the Point that you are adding is passed to VC as an LPDISPATCH.
RE 'set p1 = pts(0) '

You cannot do what you are proposing, since all communication
between VC an VB must use 'Automation' types.  It is not possible
to expose an overloaded [] operator to the VB.

You could just treat Points as a VB array and then pass it to C++ once all the Point objects are created and put into the array.  The VB array is what is called a SAFEARRAY, and it would be passed to VC as a VARIANT that contains a SAFEARRAY. You would have to write some pretty tricky code to get the values out from a VB SAFEARRAY passed to VC. Read about it and see if it makes sense to you.

OR to do the same thing in VC:

In order to do what you want, you chould write something like:

void Points::SetAt(LPDISPATCH item, long index)
      // Now set the item into the
      // (internal) array at the desired index
      // assume that the array is a CPtrArray
      m_Array[index] = item;


Also, NOTE that the VC to VB communication set up by ClassWizard
doesn't set up the internal array you'll need to create for storing the items you want to collect using either the Add() call we discussed yesterday or the SetAt() above.

You have to create the array as part of the class, perhaps in
the constructor.  The Add() or SetAt() methods just give you a way to pass the items from VB to VC++ where you can then write C++ code to put the items into the C++ array.

Go to the documentation and read CPtrList and CPtrArray.

Also, don't forget to review the AddRef and Release methods
from IDispatch.

Good Luck.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.