Главная страница | назад





Article #19624: "A class name TOCXProxy already exists"

 Question and Answer Database

     FAQ: FAQ4624C - "A class name TOCXProxy already exists"
Category: ActiveX/OLE/COM/ActiveForm
Platform: All-32Bit
 Product: C++Builder3.x,   

Question:

I have a problem with importing active x control to BCB3.0. I imported
MS Agent Control without any problem but now i'm trying to import a new
ActiveX control but it gives the following error, "a class named
TOCXProxy already exist". How can i solve this? 



Answer:

This is a problem of the wrappers (and the C++ compiler RTTI info). More
details follow but more importantly: it was fixed in the v3.0 patch. Of
course, you have to use TLIBIMP since we did not patch the IDE in that one.


Two workarounds:
(1) Download the v3.0 patch and run the TLIBIMP.EXE utility on the control.
Put the xxxx_TLB file in your default imports location (LIB directory in
v3.0 ??) and reimport. The IDE will detect the presence of the file and ask
you whether you want to overwrite the file. Say 'No' and you should be OK.
(2) Import all of your OCXes into the *same* package. (See the technical
issue below for more information).


The problem with "A class named TOCXProxy already exists"
===============================================
All ActiveX Controls imported in the IDE are wrapped in a
TOleControl-derived wrapper. The wrapper presents a VCL component to the
IDE. So, from the IDE's point of view, it's dealing with a VCL component.
The TOleControl-derived class exposes methods and properties of the
underlying ActiveX Control. Several of these properties are of standard
types. So instead of generating a 'get_Name/set_Name',
'get_Caption/set_Caption', 'get_FilePath/set_FilePath' for each 'string'
property, we optimize the access of similar types via routines in the base
class TOleControl. So TOleControl exposes a bunch of
'GetTypeNameProp/SetTypeNameProp' such as 'GetStringProp', 'SetStringProp'.
All these routines need to know is the dispid of the methods in the Control.

(A side-note here: You've guessed it, these routines go through
IDispatch::Invoke. This optimization was great in the days of
dispinterfaces. With dual interfaces, it's not the most efficient; however,
AxControls are in-proc: IOW, it's not as bad as a cross-apartment or
cross-process Proxy/Stub: In the future, we might opt to stop using these
methods; we'll need to run some performance analysis to determine whether
it's worth it to switch)

So, TOleControl exposes GetxxxxProp and SetxxxxProp for all standard types.
Unfortunately, TOleControl was not designed with C++ typenames in mind. So,
for example, while it exposes a 'GetSmallintProp', it does not expose a
'GetShortintProp'. However, DCC32 and SYSDEFS.H dictate that Pascal
Smallints will be exposed as Shortints in C++. Similarly, TOleControl
exposes a GetWordBoolProp that returns a 'WordBool', which is really an
short. However, VT_BOOL properties must really be exposed as 'bool' if you
want the user to get a 'True'/'False' choice from the ObjectInspector at
design time. So bottom line, there we a bunch of methods missing from
TOleControl for C++ usage.

Now, you'd think that we could simply add these methods to TOleControl. No!
While C++Builder fixes bugs found in VCL packages, we don't change the
interface exposed because Delphi and C++Builder share the same package
names. IOW, when C++ Builder ships, we don't want the users to install new
packages that break their Delphi installation because the interface (vtable
layouts, public entry-points, etc) is different. 

Back to the missing methods: Since we love templates, we figured we can provide
the missing methods via a template, TOCXProxy, that exposes the methods and
uses the primitives accessible in my TOleControl-derived class: We used the
ATL style TOCXProxy derives from T. We used a template because we wanted to
only pay for what is needed: i.e. If a Control does not expose boolean
properties, GetBooleanProp is not instantiated.

In the meantime, the C++ compiler individuals are talking about how to
represent template RTTI information to the IDE. That information is used by
IDE to know which class is in what package etc. Since the C++ IDE shares
packages built in Delphi (most of them are), the RTTI information uses the
least common denominator. So, they opt to encode the template using the
template name.

Now comes a rule of packages: Any given class must reside in one and only
one package. This is obvious; otherwise what information you get from the
ObjectInspector about properties, what methods/properties display in the
kibitzing window, what symbols you link to, etc would be non-deterministic
and probably catastrophic.

Now, you can imagine how all these threads converge to create the problem:
Everyone starts testing ActiveX by importing to the single/provided package.
The RTTI information encodes TemplateOf as TemplateOf so that
TemplateOf and TemplateOf are encoded as the same
type. Someone who thinks out of the box tries to import an ActiveX control into a
different package and BAM!!!!



8/4/99 11:49:42 AM
 

Last Modified: 01-SEP-99