MFC ActiveX control

Posted on 2001-08-23
Last Modified: 2013-11-25
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.
Question by:IainHere
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3

Expert Comment

ID: 6419738

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.


Author Comment

ID: 6419817
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?

Accepted Solution

peterchen092700 earned 100 total points
ID: 6420044
>> "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?

Percona Live Europe 2017 | Sep 25 - 27, 2017

The Percona Live Open Source Database Conference Europe 2017 is the premier event for the diverse and active European open source database community, as well as businesses that develop and use open source database software.


Author Comment

ID: 6421202
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 :-)

Author Comment

ID: 6421312
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.

Expert Comment

ID: 6421429
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


Expert Comment

ID: 6421430
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..

Author Comment

ID: 6421457
>> 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 :-)

Featured Post

 Watch the Recording: Learning MySQL 5.7

MySQL 5.7 has a lot of new features. If you've dabbled with an older version of MySQL, it is definitely worth learning.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

What my article will show is if you ever had to do processing to a listbox without being able to just select all the items in it. My software Visual Studio 2008 crystal report v11 My issue was I wanted to add crystal report to a form and show…
In this post we will learn different types of Android Layout and some basics of an Android App.
The purpose of this video is to demonstrate how to set up the WordPress backend so that each page automatically generates a Mailchimp signup form in the sidebar. This will be demonstrated using a Windows 8 PC. Tools Used are Photoshop, Awesome…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.

632 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question