Accessing Hidden VB Interfaces

The Microsoft KnowledgeBase article Q193018 in MSDN lists the problem that Visual C++ programs cannot access hidden Visual Basic interfaces that are defined with an underscore ( _ ) as the first letter in the name, such as the Visual Basic Collection interface declared in MSVBVM60.DLL.

This article will depict the simple solution for this task of using VB hidden object interface in VC project. I will show how to import VB Collection object from VB Control to VC application.

This is a common situation. For example, if you are making an ActiveX control in VB , and this control uses the VB Collection object in order to stor several items. There might be a situation in which you would like to have a way to access this object from a VC application.

There are several steps to make things work:

The first step is to make ActiveX control. This example shows a simple ActiveX control which has a collection of Cars. the cars have a CarId which identifies them. The control keeps a VB Collection Object to store all the Cars Id's. We would like to get this Collection from VC application.

The control has two interface functions

AddCar(car as Integer) which adds a car to the collection

and Cars(ByRef cars as Variant), which reterns a reference to the cars collection.

1) bulid the project in order to produce CarControlProject.ocx, and register the control in your computer using RegSvr32.exe utility.

2) Open new Dialog based VC application. and put this Control on the dialog. Add member variable to your dialog which will be with type CUserControl.

3) Now, we would like to get the collection of cars that this control holds. This is tricky and requires several steps:

1) Find out what is the IID of the requested object. In our example we would like to receive a pointer to _Collection object. Open the OLE-COM viewer and display the information of all available interfaces. look for the interface _Collection.

There are probably several _Collection interfaces. look for the one which is declared as VisualBasic For Applications Component.

3) generate an .idl file for the object and run MIDL to compile this interface.

Here there are no shortcuts. we have to write the interface. However we do not have to do it from scratch. we can use information retreived from the OLE-COM viewer.

Here is the .idl file that I wrote for _Collection object. using the information from OLE-COM viewer. save this file as Collection.idl

NOTE: The interface ID - IID must be as the one you saw in the OLE-COM map viewer. Cut and Past the IID from the OLE-COM viewer tool to avoid mistakes.

import "oaidl.idl";

import "ocidl.idl";
[
 object,
 // The uuid was taken from OLE-COM viewer.
 uuid(A4C46780-499F-101B-BB78-00AA00383CBB),
 helpcontext(0x000f7886),
 dual,
 pointer_default(unique)
]

 interface _Collection : IDispatch
 {
  [id(
   helpcontext(0x000f7903)]  HRESULT Item([in] 
   VARIANT* Index, [out][retval] VARIANT *Item);

  [id(2), helpcontext(0x000f7901)]  HRESULT Add( 
  [in] VARIANT* Item, [in, optional] VARIANT* Key, 
  [in, optional] VARIANT* Before, 
  [in, optional] VARIANT* After);

  [id(3), helpcontext(0x000f7902)]  
  HRESULT Count([retval][out] long *count);

  [id(4), helpcontext(0x000f7904)]  
  HRESULT Remove([in] VARIANT* Index);
 };

compile this file using MIDL compiler. The compiler will generate the files which are needed in order to use this interface in our VC application.

first Collection_i.c the definition of the IID of the interface. - add it to the project, in order that the linker will find the IID symbol.

and the Collection.h file. Header file for the _Collection interface.

4) Now, we wish to invoke the Cars member of our Control. This method will give us a refrence to the Connection object.

Pass the method a pointer to Variant object.

#include "Collection.h"

COleVariant vrCars;

HRESULT hr;

interface _Collection *ICol;

 m_myCar.Cars(&vrCars);

vrCars.ChangeType(VT_UNKNOWN);

5) Use QueryInterface to get The requested interface pointer. In our case, a pointer to the _Colleciton interface

hr = vrCars.punkVal->QueryInterface(IID__Collection, (void **) &ICol);

6) Use this pointer to access the Collection.

long l;

// Call the Collection count method
ICol->Count(&l);    

for (long i=0;i < l ; i ++)
{
 // Get all the Items of the Collection.
 COleVariant vrIndex;

 COleVariant vrValue;

 vrIndex.ChangeType(VT_I4);

 vrIndex.lVal = i;

 vrValue.ChangeType(VT_BSTR);

 _bstr_t bstr(vrValue.bstrVal,true);

 m_listCars.AddString(bstr);
}

Downloads

Download demo project - 8 Kb


Comments

  • How to return Variant data as array from activex dll/exe to VC client

    Posted by Legacy on 01/09/2002 12:00am

    Originally posted by: ashutosh

    hi,
    
    there is any way to take variant data e.g.
    myfunc() as variant
    dim a as variant
    dim b() as ..... any
    a = b
    myfunc = a

    above is sample of a function in activexdl/exe server
    now i want to call that function in vC++ client and i want
    same array in return.
    i used VARIANT structure in vc , but i failed,
    can any one suggests me.
    thanking u
    ashutosh

    Reply
  • problem with _recordset like

    Posted by Legacy on 01/02/2002 12:00am

    Originally posted by: Antonio Ramirez

    I'm developing a multithreaded app, pointers like
    
    

    progress bars and edit boxes work fine inside a
    AfxBeginThread class

    m_prop->m_progress.SetPos(resbarra);//where m_prop CDialog*

    but pointers like

    res=m_prop->m_mail2.SendMail(&conect,&nob);

    error "Access violation" is displayed in runtime.

    m_mail2 was declared like

    C_vbSMTPOCX m_mail2;

    and

    #include "_vbsmtpocx.h"

    I got the same problem for _recordset like declarations.

    does anybody know how to solve this problem? or is there any service pack that solves this?

    Thanks

    Reply
  • Problem with Add !!!

    Posted by Legacy on 05/18/2001 12:00am

    Originally posted by: Daren

    Your walk though has been very useful , but alas I still have a problem that you may be able to help me with ....
    I am currently unable to Add items into the collection from VC++ !

    I am creating a COleVariant vrItem and giving it an int and defining 3 COleVariants as VT_EMPTY , and passing all 3 into the collections ->Add method ... but alas the item is not being appened to the collection .... and no error surfaces either ...


    Please could someone help me ...

    MTIA Daren 'Well and Truely Stuck'

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • IBM Worklight is a mobile application development platform that lets you extend your business to mobile devices. It is designed to provide an open, comprehensive platform to build, run and manage HTML5, hybrid and native mobile apps.

  • Recently, Forrester Consulting conducted a Total Economic Impact™ (TEI) study to better understand the impact of incorporating Polycom voice solutions with Microsoft Lync. Forrester interviewed a company that had already deployed the Lync/Polycom combination to determine its potential return on investment (ROI). Microsoft Lync provides presence information and promotes voice and video collaboration. Polycom extends the benefits of Lync with voice endpoints and further enables collaboration in multiple …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds