How to create ActiveX control supporting Automation

Hi,
      I have created a basic ActiveX control using MSVC++ 5.0 Control Wizard. I added one arbitrary method, and compiled it.  
      When I use the control in VB 5.0, it works as long as I place the control on the form and access its method that way. But if I use automation, such as in the following VB code,

Dim obj as Object
set obj = CreateObject("MyControl.mycontrol.1")
obj.MyMethod  ,

I get the error:

Run-time error -2147418113 (8000ffff)
Method 'MyMethod' of object '_DMyControl' failed.

(The error number is S_UNEXPECTED in VC++, and it occurs because the m_bInitialized member variable is false in the instance of COleControl - I tried the equivalent of "CreateObject" in VC++ and the I got the same error)

There must be something simple that I am missing out on...I thank you in advance for any help.

..............................Lee

(FYI, the CreateObject statement seems to function properly, as I do get a pointer to my control when debugging)

PS: Instead of trying to instantiate the other object using "CreateObject" (or the equivalent set of C++ functions), can one get a pointer to an ActiveX control from within another ActiveX control given that they both reside in the same container???
leeorAsked:
Who is Participating?
 
gelbertConnect With a Mentor Commented:
You have to load control state to initialized m_bInitialized property to TRUE by calling COleControl::Load() which is wrapper around IPersistXXX::Load() function (IPersistStorage, IPersistFile,....)
0
 
leeorAuthor Commented:
Edited text of question
0
 
leeorAuthor Commented:
Adjusted points to 200
0
Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

 
leeorAuthor Commented:
Edited text of question
0
 
gelbertCommented:
Can you show your VC++ container code ?
0
 
leeorAuthor Commented:
Hi Gelbert,
   Sorry, I guess I was not clear enough. The container is a VB form (although I should not depend on one specific container, of course). If you mean my VC++ code which instantiates the ActiveX control - it performs the same function as CreateObject(), but here it is anyway...

        // Set GUID
      long a = 1163048501;  
      short b = 13338;            
      short c = 4561;      
      unsigned char d[8] = {150,34,0,0,192,52,105,210};

      GUID g;
      g.Data1 = a;
      g.Data2 = b;
      g.Data3 = c;
      for (int i =0; i<=7; i++)
            g.Data4[i] = d[i];      

      if (int r = OleInitialize(NULL) != S_OK)
            TRACE("OleInitialize() failed!\n");

      REFCLSID CLSID_CMyObject = g;

      HRESULT hresult;
      IUnknown FAR* punk;
      IDispatch FAR* pdisp = (IDispatch FAR*)NULL;

      LPCTSTR methodName = "putNoText";

      USES_CONVERSION;

      LPCOLESTR lpOleStr = T2COLE(methodName);

      DISPID dispid;
      DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};

      hresult = CoCreateInstance(CLSID_CMyObject, NULL, CLSCTX_INPROC_SERVER, //CLSCTX_SERVER,
                        IID_IUnknown, (void FAR* FAR*)&punk);

      if (hresult != S_OK)
            TRACE("CoCreateInstance failed!\n");

      hresult = punk->QueryInterface(IID_IDispatch,
                  (void FAR* FAR*)&pdisp);
      if (hresult != S_OK)
            TRACE("QueryInterface (IDispatch) failed!\n");

      IUnknown FAR* punknown = (IUnknown FAR*)NULL;
      LPDWORD lpdwRegister = (LPDWORD)malloc(64);
      hresult = punk->QueryInterface(IID_IUnknown,
                  (void FAR* FAR*)&punknown);

      if (hresult != S_OK)
            TRACE("QueryInterface (IUnknown) failed!\n");

      hresult = CoRegisterClassObject(CLSID_CMyObject, punknown, CLSCTX_INPROC_SERVER,
                        REGCLS_MULTIPLEUSE, lpdwRegister);

      if (hresult != S_OK)
            TRACE("CoRegisterClassObject() failed!\n");

      unsigned long FAR* pdwRegister = (unsigned long FAR*)malloc(64);
      hresult = RegisterActiveObject(punknown, CLSID_CMyObject, ACTIVEOBJECT_STRONG,
            pdwRegister);

      if (hresult != S_OK)
            TRACE("RegisterActiveObject() failed!\n");

      hresult = pdisp->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpOleStr, 1,
                        LOCALE_USER_DEFAULT, &dispid);

      if (hresult != S_OK)
            TRACE("GetIDsOfNames failed!\n");

      hresult = pdisp->Invoke(
            dispid,
            IID_NULL,
            LOCALE_USER_DEFAULT,
            DISPATCH_METHOD,
            &dispparamsNoArgs, NULL, NULL, NULL);

        // This is where the failure occurs - all other functions
        // complete successfully
      if (hresult != S_OK)
            TRACE("Invoke failed!\n");


0
 
gelbertCommented:
When you use CoCreateInstance() ask for IClassFactory insterface and use it ot call IClassFactory::CreateInstance() to create instance of object
0
 
leeorAuthor Commented:
Didn't work.....
Let me make my question simpler...

1) I created an ActiveX control using VC++ 5.0 control wizard.
2) I added 1 method called "Method"

3) I created another ActiveX control using VC++ 5.0 control wizard.
4) In the second control, I am trying to invoke the method on the first control.

I have failed to do this so far, and have tried everything I could think of.  If you have any idea (or source code example) please let me know. Thanks.

P.S. I am using VB as the form on which the second control is placed.
0
 
leeorAuthor Commented:
hint: the CoCreateInstance and CreateInstance functions create an UNINITIALIZED (what does that mean?) object. The error I am getting is within the COleControl class, where the variable m_bInitialized = FALSE when it should be true. Is there someway to "initialize" an ole object that I do not know about???
0
 
leeorAuthor Commented:
I already checked that option, but I do not have a pointer to the control, but merely a pointer to its interfaces. Anyway, like I said before, my C++ code is the equivalent to the Visual Basic "CreateObject" function, and that did not work.  I think I have figured out the problem - it is that the new (VC++ 5.0) activeX wizard creates more lightweight controls than (VC++ 4) and as such have left out certain interfaces such as some automation ones, and so I need to add them manually. Thanks for the help anyway...I'll give u the points for good effort.
0
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.