MFC ActiveX control

I have an MFC ActiveX control, one property of which should expose an ATL COM object from within the same dll.  The ATL object is a collection of other ATL objects, although I don't *think* that's important.

My problem is that, although I can get the interface to recognize what I'm trying to do (ie in VB the intellisense works) I can't get the COleControl to expose the custom control.

I'm new to this, so I guess I'm looking for someone to hold my hand a bit through it.  Depending on how complicated the question is, I might raise the points.

Some background info:

the odl code for the interface:
[propget, id(2)] long Series([out, retval] ISeriesCollection* *pVal);

where ISeriesCollection is my interface to the ATL object which is a collection of ATL objects.

the declaration of the corresponding class declaration (within the AFX_DISPATCH comments):
afx_msg long GetSeries(ISeriesCollection **pVal);

The definition after the BEGIN_DISPATCH_MAP() macro:
DISP_PROPERTY_PARAM(CGraphMFCCtrl, "Series", GetSeries, SetNotSupported, VT_R8,VTS_VARIANT)

I've seen some code for how to do this exact thing with ATL, but my control is MFC.

All help gratefully accepted.
Who is Participating?
peterchen092700Connect With a Mentor Commented:
>> "Parsing Error: ISeriesCollection **pVal is not a valid OLE Parameter type"

The problem is, OLE does only know about IDispatch. I know that VB no supports custom (IUnknown-based) interfaces as well, if all functions use OLE compatible types only - but I dubt thar you can accept MFC to accept another interface than IDispatch in an automation-compatible object.

I assume your ISeriesCollection is a dual interface (i.e. inherited from IDispatch, provides both early and late binding). If not, you've got to do that again ;)

Change the declaration of the propget to returning an IDispatch * (rather than ISeriesCollection).

As I don't know how you implemented the collection, I assume the usual way: You create an Instance of the SeriesCollection, feed it with an pointer to the SeriesContainer (a chart?), cst it to IDispatch, AddRef it, and return.  The creation of the ATL component is like I described in your last question ;) - I have no MSDN/Source of me here, so it's right out of my brain:

GetSeriesCollection(IDispatch ** disp)
  (if !disp) return E_POINTER;
CComObject<CSeriesCollection> * sc = 0;
HRESULT hr = CComObject<CSeriesCollection>::CreateInstance(&sc);
// up to here compare w/ my answer to your last question
if (FAILED(hr)) return hr;

sc->SetOwner(this); // this is passing a CChart * to the container - i.e. this is not a COM method. this allows the two to communicate directly, rather than through C++ interfaces)

sc->AddRef();  / we are returning a pointer, s owe have to addref
*disp = static_cast<IDispatch *>(sc);
return S_OK;

There might be some problems in VB to make intellisense work - I'm not sure here, but the standard ODL declaration (the SeriesCollection object suports an ISeriesCollection interface) should be enough here.

So far, did it help to take a step?


Trick is to make ATL Code treat your MFC control
as a client for the interface. You could try
aggreagation, but that does not sound too good
atleast not right away.

Go through the CoCreateInstance (CoGetClassObject)
rigmarole in MFC to create interface ISeries...

I guess intellisense worked, bcos it used your .tlb
and not really used actual object.

What exactly is the nature of error message.

IainHereAuthor Commented:
Sorry if I'm being rather vague - it's always a problem when someone doesn't understand what they're trying to do :-)

Everything compiles OK, but only because I haven't done anything.  What I'm asking for is advice on how to do it.  The error message I've seen has occurred when I changed the GetSeries function to expose an ISeriesCollection in the way I wrote it above.  Now, if I try to use the ClassWizard on the interface, it says

"Parsing Error: ISeriesCollection **pVal is not a valid OLE Parameter type"

But I thought that, since I'd defined it, I could use it?  Am I being naive?
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

IainHereAuthor Commented:
Thanks again peter.  I'll try what you're describing; I hope you don't mind me keeping the Q open for a little longer, until I understand what you said :-)
IainHereAuthor Commented:
OK.  I'm still lost:

1) "Parsing error IDispatch** is not valid etc.  I hacked an attempt at IDispatch* and IDispatch, neither of which were happy.  Can I safely ignore this message?

2) Do I have to implement SetOwner() myself?  I can't find it.

I would go away and RT(F)M, if I could find one.  Thanks.
1) is it declared as [out, retval] ?
2) SetOwner:

yes, it's actually quite simple:
class CChart : public IChart, ....

class CSeriesCollection
  CComObject<CChart> * m_chart;  // init to 0
  void SetOwner(CChar * chart)
     if (chart) chart->AddRef();
     if (m_chart)  m_chart->Release();
     m_chart = chart;
   ~CSeriesCollection() { SetOwner(0); }

the SeriesColleciton now has full access to the chart, so it can iterate over it's items. Note that the colleciton has a reference to the chart, so the chart will be "kept alive" by any "living" SeriesCollection.

Another option would be the SetOwner function to copy the Series Interface Pointer list (addrefing it), and not keeping a reference to the chart.

3) Yeah, MSDN can be a pain. There's all informaiton you need, buried under 1000 tons of marketing sh*t

P.S. keeping your Q open as long as you're not satisfied is quite ok. Only thing that could happen that I gently withdraw from the question..
IainHereAuthor Commented:
>> is it declared as [out, retval] ?
Yes (all the declarations and stuff are as they were described in the original Q, excapt they've been corrected to IDispatch).  I think I'll ignore the message for now, and see what happens.  If you can think of anything else it might be, I'd be grateful for the info.

Thanks for the help.  I'll take the hint, and open another question when I have my next problem.  Hope you'll feel like helping me again :-)
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.

All Courses

From novice to tech pro — start learning today.