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.
|