2

We build an OCX that contains a Map control and many supporting classes (e.g. GeoProjection, Extents) which can act as standalone classes and many of which are also Properties of the Map.

One of our legacy applications that uses the OCX is built in Visual Basic 6. After updating the build from VS2013 to VS2015, we noticed differences in how we have to access some of the properties from VB6. The two in particular that we had problems with were the Map.GeoProjection and the Map.Extents properties. They both started raising "Library Not Registered" errors when attempting to use them.

In the case of the GeoProjection, I was able to resolve the problem simply by adding the VB 'Set' command to the assignment, as follows:

Dim gp As New GeoProjection
gp.ImportFromEPSG m_MapProjection ' contains the EPSG code
Set Map.GeoProjection = gp.Clone

Why the 'Set' wasn't required before this, I don't know. It seems like it should have been since it is setting an object reference.

Even so, when I tried to do the same with the Extents property, it did not resolve the problem, but instead resulted in an "Automation Error". So I next went to review the IDL and MFC macro definitions to see how the definitions differed and why the behavior might differ.

The GeoProjection IDL

[id(192)] IGeoProjection* GeoProjection;

end the Extents IDL

[id(17), propput, nonbrowsable] void Extents(IExtents* nNewValue);
[id(17), propget, nonbrowsable] IExtents* Extents();

The GeoProjection dispatch macro

DISP_PROPERTY_EX_ID(CMapView, "Projection", dispidProjection, GetGeoProjection, SetGeoProjection, VT_DISPATCH)

and the Extents dispatch macro

DISP_PROPERTY_EX(CMapView, "Extents", GetExtents, SetExtents, VT_DISPATCH)

What particularly struck me was the difference in using the DISP_PROPERTY_EX vs the DISP_PROPERTY_EX_ID. Ironically, I can find no Microsoft Documentation on DISP_PROPERTY_EX_ID. The only guidance I could find were comments in the afxdisp.h file, where it describes the two groups of macros, as follows:

on line 288, prior to the macros without the _ID suffix

// these DISP_ macros cause the framework to generate the DISPID

and on line 313, prior to the _ID suffixed macros

// these DISP_ macros allow the app to determine the DISPID

Since we have an .h file that defines dispatch IDs for every function, it seems that we should always use those IDs within the macros, as follows. This assures that the Dispatch IDs will always be the same (which I think would matter when using early-bound COM calls).

DISP_PROPERTY_EX_ID(CMapView, "Extents", dispidExtents, GetExtents, SetExtents, VT_DISPATCH)

Once I made changes to the Extents property in the IDL

[id(17)] IExtents* Extents;

and in the use of the DISP_PROPERTY_EX_ID macro, we were able to successfully set the Extents property from VB6 using the 'Set' statement.

In summary, I don't really know

  1. why the behavior changed in the first place (from VS2013 to VS2015)?
  2. why my changes made things start working again (I have my theories)?
  3. what is the recommended methodology going forward?
    a. IDL syntax allows for property definition without having to specify propput and propget. Is one syntax recommended over the other?
    b. should I change all of our macros to use the _ID suffixed macro?

Any insight is appreciated.

Thank you.

JDog
  • 21
  • 2
  • 1
    Indeed your declarations seems quite outdated... What's important for a COM client such as VB6 is the .TLB file. That's what defined how VB6 will "see" your COM server. When you use OleView, do you see any difference in the output .TLB (note sometimes it's embedded with the .DLL)? – Simon Mourier May 24 '19 at 20:23

0 Answers0