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