C++ Builder
Exontrol.COM Software - Frequently Asked Questions
CBI.0:
In RAD Studio C++ 32-bit you can use any of the following versions:
  • /COM indicates the 32-bit edition of the ActiveX version

The application built using /COM version runs on any Windows 32 or 64-bit machine.

In RAD Studio C++ 64-bit you can use any of the following versions:

  • /COM/64 indicates the 64-bit edition of the ActiveX version

The application built using /COM/64 version runs on Windows 64-bit machine only. The application built using /COM/64 version cannot run on Windows 32-bit machine.

If you want to use your application on 32 and 64-bit machines, you can go for:

  • /COM/ANY indicates the 32 and 64-bit editions of the ActiveX versions

Should I use a 32-bit or 64-bit version of the control?

CBI.1:
The compiler cannot distinguish what function is called. The most common could be the Add method of the Columns object as it generates two Add functions in the wrapper classes with the same name and parameters, as described later.

This problem can be solved by removing the TNoParam() parameter (missing parameter), to let complier chooses the correct function to use in the code, like explained bellow.

For instance, the compiler error you get is:

[BCC32 Error] E2015 Ambiguity between '__stdcall Exg2anttlib_tlb::IColumns::Add(wchar_t *,tagVARIANT *) at ..\9.0\Imports\EXG2ANTTLib_TLB.h:2264' and '_fastcall Exg2anttlib_tlb::IColumns::Add(wchar_t *) at ..\9.0\Imports\EXG2ANTTLib_TLB.h:2287'

All you need is to locate these two declarations in the EXG2ANTTLib_TLB.h file as follows:
virtual HRESULT STDMETHODCALLTYPE Add(BSTR ColumnCaption/*[in]*/, VARIANT* pVal/*[out,retval,opt]*/= TNoParam()) = 0;

and

VARIANT __fastcall Add(BSTR ColumnCaption/*[in]*/)
{
   VARIANT pVal;
   OLECHECK(this->Add(ColumnCaption, (VARIANT*)&pVal));
   return pVal;
}

The TNoParam() in the first declaration makes the compiler to be not able to find the function Add. 

In order to prevent this remove the TNoParam() from the declaration and save the changes so the new declaration is:

virtual HRESULT STDMETHODCALLTYPE Add(BSTR ColumnCaption/*[in]*/, VARIANT* pVal/*[out,retval,opt]*/ ) = 0;
CBI.2:
This error could appear when a /COM 32 or 64 bits module is hosted by a Delphi, C++ Builder application ( 2009, 2010 ).

The solution is disabling the FPU exceptions using the Set8087CW method as follows:

C++Builder

	#include "float.h"; 
	void disableFpu() { 
		_control87(PC_64|MCW_EM,MCW_PC|MCW_EM);        
	}
Delphi 3 or higher
	procedure DisableFpu;
	begin 
	  Set8087CW(Default8087CW or $3F); 
	end; 

"This is not so much a bug as an incompatibility between different compilers. There's a detailed explanation below. In short, what happens is that Delphi and C++Builder set the control word of the processor to a certain state, and applications or dlls written in Visual C++, for example, set it to a different state. This causes crashes (more precisely: floating point division by zero exceptions)."

Other notes:

Thanks to Jamie Rorrison, MindGenius Ltd, who submitted the note.
CBI.3:
The error occurs because two components install two separate objects with the same name.

The solution is replacing the ambiguous name in the generated h and cpp files. 

So, in order to avoid the name collisions with TeeChart (and others lib which would use TItem, TChart etc...), it's as easy as doing a whole word search and replace in the generated h and cpp by C++ Builder from the DLL/OCX and replacing TChart by TExChart for example

Install again the package by replacing all name collisions, until you get the message "Package ... has been installed". Once this message occurs, the Tool palette will include the component being inserted. Once you get the component on the Tool palette, you can insert to the application's form.
CBI.4:
Generally, this exception or error occurs due non-initialized VARIANT variables in generated wrapper classes.

 For instance the get_CellValue function being generated in the TLB.h file is:

VARIANT __fastcall get_CellValue(VARIANT Item/*[in,opt]*/= TNoParam(), VARIANT ColIndex/*[in,opt]*/= TNoParam())
{
	VARIANT pVal;
	OLECHECK(this->get_CellValue(Item, ColIndex, (VARIANT*)&pVal));
	return pVal;
}

while the correct would be:

VARIANT __fastcall get_CellValue(VARIANT Item/*[in,opt]*/= TNoParam(), VARIANT ColIndex/*[in,opt]*/= TNoParam())
{
	VARIANT pVal = {0};
	OLECHECK(this->get_CellValue(Item, ColIndex, (VARIANT*)&pVal));
	return pVal;
}

In conclusion the solution is replacing all occurrences, in TLB.h generated files looking for:

  • VARIANT pVal;

and replace with:

  • VARIANT pVal = {0};
CBI.5:
If you are using the eXG2antt component, this may happens, if the initialization code is called during the FormCreate event instead using the FormShow. Some internal functions of the control requires the size of the component, and during the FormCreate the size of it is 0,0 and so some objects may not be available.

The solution is move the initialization code from FormCreate event to FormShow event. 

We would recommend pasting the generated C++ Builder code from the eXHelper to FormShow event.
CBI.6:
The names conflict may occurs if installing multiple exontrol components to a single package. 

In order to prevent names conflicts we would recommend installing the components in separate packages as explained bellow.

In my opinion this problem occurs when the user wants to  install the components on the "Tool palette".

>From "Tool palette" the components can be drag and drop to the Form, it will have a visual appearance on the form.

For this the user have to do the followings: "Component->import component" -> choose the type of component (in my case activex)->select the component from the registered activex component list -> select palette page (activex) and check the "generate component wrappers".

So there are three choices: 

  1. create unit. 
  2. install into existing package 
  3. install into new package

My choice was always the 2., because good to know all of my EX components are in one package, but it seems the 3. is the recommended solution, and all components should have installed into separated packages.

The renaming can be very complicated when somebody wants to install five components or more. I have to rename to TExDataObjectFiles, TEx2DataObjectFiles, TEx3DataObjectFiles.... and so on.

Can be easier to comment out the conflicting names in the OCX file, it will cause these names will not appear in the class list of the package, but it is no problem, because it was already defined in another package (if I am not mistaken). But I do not know if the commenting has any other negative impact.

TComponentClass cls_svr[] = {
                              __classid(Exfileviewlib_tlb::TFileType),
                              __classid(Exfileviewlib_tlb::TFileTypes),
                              __classid(Exfileviewlib_tlb::TFiles),
                              __classid(Exfileviewlib_tlb::TFile),
  //__classid(Exfileviewlib_tlb::TExDataObjectFiles),
  //__classid(Exfileviewlib_tlb::TExDataObject),
  //__classid(Exfileviewlib_tlb::TAppearance),
                            //__classid(Exfileviewlib_tlb::TTemplatePage)

Other solution can be if you provide a renaming tool or some similar.

In conclusion, if using multiple exontrols to C++ Builder project, install them in separately packages.

Thanks to Pataki L�szl�, GfK Hungary, who submitted the note.
CBI.7:
This error could appear when a /COM 32 or 64 bits module is hosted by a C++ Builder application.

The EVariantBadVarTypeError is the exception class for variant type errors. The EVariantBadVarTypeError is raised when a variant operation fails because of a value that isn't a valid variant type

The C++ Builder is not able to handle the events of Variant type, so the generated TLB file requires some changes for events that carries parameters of the Variant type, events such as BarResize, BarParentChange and so on. Running a sample with such of event handled, fires "Project raised exception class EVariantBadVarTypeError with message 'Invalid variant type'. Process stopped. Use Step or Run to continue." 

In order to prevent this, you can use the 

  • Event handler and the EventParam properties to handle the BarResize event instead. For instance, the Event(120) is fired when the BarResize event occurs. The EventParam(0) gets the handle of the item where the bar is resized, and the EventParam(1) gets the key of the bar being resized. The EventParam property has effect only if it is called during the event itself. Calling outside the event, has no effect.
  • Change or make the adjustments in the BarResize defintion as explained here.
CBI.8:
An application is considered an isolated application if all of its components are side-by-side assemblies. A side-by-side assembly is a collection of resources?a group of DLLs, windows classes, COM servers, type libraries, or interfaces?available for an application to use at runtime. Typically, a side-by-side assembly is one to several DLLs. 

Isolated COM allows your application to use ActiveX components without having to register them. The original vision of this was to allow copy deployment of the application, but Isolated COM has many benefits. You can have a private copy of the DLL without worrying that another application will install an older or newer copy that breaks your application. Isolated COM also allows you to successfully install and run on non-Administrator accounts.

The solution is to include the control's manifest file to the application's resource under 24( Manifest Resource Type ) with the identifier 1.

  • Open the Project\Options
  • Go to Application
  • Select at Runtime Themes field the "Use custom manifest"
  • At the Custom Manifest field fills or select the exg2antt.manifest file
  • Build the project

Now, copy the generated EXE and the exg2antt.dll to a client machine, and run the EXE. It will work, as in this case, the application uses the exg2antt as isolated, so it requires no registration ( regsvr32 ).

You can download it here the C++ Builder XE7 project. In the Release folder, you can find the sample.exe that uses the exg2antt.dll as isolated.

See also: How to Generate Assembly Manifest File (Registration-Free)?