t e m p o r a l 
 d o o r w a y 

A Workaround For ActiveX Component Inheritance Problems In C++ Builder 4

 

Introduction

Some ActiveX controls when imported into BCB4 experience problems when a derived component is created from the generated class. This problem is currently being investigated by Borland. In the meantime, the following workaround is of use.

The Workaround

One of the symptoms of this problem is that it only occurs with a derived control. Therefore we use the aggregation to overcome the problem and provide a different base for inheritance than the ActiveX control itself.

First, derive a new component from TWinControl or TPanel. In its class definition add a private variable for a pointer to an instance of the base ActiveX control from which you want to derived. In the constructor, create an instance of that control into that variable with "new" and set ownership and parentage to the TWinControl / TPanel. Use alignment of alClient, and, if you are using a TPanel, set the borders to none. The following is an example:

__fastcall TBaseContainsBadActiveX::TBaseContainsBadActiveX(TComponent* Owner)
   : TPanel(Owner)
{
   myBadActiveX = new TBadActiveX(this); // Initialize the class variable
   myBadActiveX->Parent = this; // Parent it
   Width = myBadActiveX->Width;
   Height = myBadActiveX->Height;
   BorderStyle = bsNone;
   BorderWidth = 0;
   BevelInner = bvNone;
   BevelOuter = bvNone;
   BevelWidth = 0;
   myBadActiveX->Align = alClient; // Align it to fill the panel
}

Next, copy the method headers from the ActiveX control to the new component header class definition. Have the methods inline to delegate their call to the internal control's methods, as follows:

void __fastcall SetSize(long Width, long Height){myBadActiveX->SetSize(Width, Height);};

Then copy the property declarations from the ActiveX control to the new component header class definition. Transform them to delegate getting / setting property values using macros like the following:

#define BadActiveXPublishedPropertyDelegated(Type,Name)\
   protected:\
      void __fastcall Set##Name(Type the##Name){myBadActiveX->##Name = the##Name;}\
      Type __fastcall Get##Name(void){return myBadActiveX->##Name;};\
 __published:\
      __property Type Name = {read=Get##Name,write=Set##Name};

#define BadActiveXPublicPropertyReadOnlyDelegated(Type,Name)\
   protected:\
      Type __fastcall Get##Name(void){return myBadActiveX->##Name;};\
   public:\
      __property Type Name = {read=Get##Name};

#define BadActiveXPublicPropertyDelegated(Type,Name)\
   protected:\
      void __fastcall Set##Name(Type the##Name){myBadActiveX->##Name = the##Name;}\
      Type __fastcall Get##Name(void){return myBadActiveX->##Name;};\
   public:\
      __property Type Name = {read=Get##Name,write=Set##Name};

This allows you to edit the property definitions to appear as follows:

BadActiveXPublicPropertyReadOnlyDelegated(System::WideString,Version);

Which is a fairly simple transformation.

The Derivation Of A New Component

You could add new capabilities directly to this component. However, I recommend that this component be left simply as a facade, and that you derive a component from it, instead, to which you can add properties and methods as needed.

Copyright © 2004 by Mark Cashman (unless otherwise indicated), All Rights Reserved