dcsimg

Accessing Hidden VB Interfaces

WEBINAR:
On-Demand

Desktop-as-a-Service Designed for Any Cloud ? Nutanix Frame


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

  • There are no comments yet. Be the first to comment!

  • You must have javascript enabled in order to post comments.

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

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date