Contents
3 Comments and Troubleshooting
The OLE Proxy Wizard is a tool to generate OCF/OWL based code for handling OLE Automation servers and ActiveX Servers. It reads a type library, and extracts all the information it can: for example dual interfaces get C++ abstract class definitions defined for them as well as OLE automation based proxy classes. OLE Proxy Wizard also tries to find all types that are marked as event sources and generates sample event handling code for TOleWindow or TOleDialog based classes, that you can cut and paste into your own code.
GUI Version
Most of the options for the OLE Proxy Wizard are self explanatory, but are explained here for completeness.
Page 1:
Select a registered type library from the list or click Browse to find a .tlb file to open.
Page 2:
Type the name and path for the header and source files you want to generate, you can use the browse buttons to help make the task easier if you prefer, remember that if you select an existing file then it will be overwritten!
If you select "Use Tabs" then tab characters are used to create indents in your code, if you select "Use Spaces" then the number of spaces specified in the "Space Size" edit box will be used to generate indents.
"Paranoid ID Checking" causes the generated code to lookup the Dispatch ID of automation function calls at runtime, otherwise the ID is determined at compile time from information in the type library. In general you should leave this option unchecked as this will produce faster executing code, however there are some circumstances (for example if the server is still under development) where it is necessary / safer to do a run-time lookup.
Page 3:
Enter admin options to this page, these options will be used in the comments that appear at the head of each file.
That's all there is, just click "Finish" when you're happy with the options you have selected.
Command Line Version
Most of the options for the OLE Proxy Wizard are self explanatory, but are explained here for completeness.
The generated files will be in the same directory as {typelib}.
Macros
I have tried to write readable code that doesn't contain too many macros or impenetrable declarations, so that if the code needs tweaking by hand after it has been generated it should be possible for the user to determine what's going on. One exception to my "no macros" rule are interface declarations where I've followed Microsoft style conventions to maintain both C and C++ compatibility.
Dual Interfaces
The OLE Proxy Wizard generates both interface declarations and Proxy-Classes for dual interfaces, this may seem like overkill, but you can easily comment out the proxy-class code if you decide that you don't need it. In general using the interface directly will result in much faster function calls than going through the proxy, the down side is that the code may be slightly harder to write and will require some knowledge of the COM architecture.
Fixes
There are some data types that are unsupported by TAutoVal. To fix this I've used the inline template function push_arg to provide specific fixes for TAutoVal's deficiencies.
Commented Out
Some of the code generated by the proxy wizard may be commented out, this falls into two categories: Event handlers and unreferenced classes. Event handling code is generated as a sample TOleDialog derived class which overrides EvOcCtrlCustomEvent to extract event parameters and dispatch them to appropriately typed functions. You should copy the EvOcCtrlCustomEvent event dispatching code along with the event handlers themselves to your own TOleWindow or TOleDialog derived class - the two demo app's show this in practice. Unreferenced classes are classes that have type definitions in the type library but do not appear to have any references to them from the main co-class objects in the library. Usually this means that they are "base" classes for other types already declared and as such should be left commented out and not used - they are for the internal use of the server only - however they are included just in case you should find a pressing need for them - in general you should let yourself be guided by the help file that came with the server.
NB the event handling code assumes that the TOleWindow derived class has just one OCX contained within it. If you plan to have more than one OCX within the one container, then in EvOcCtrlCustomEvent you need to check which control dispatched the event before attempting to dispatch the event to a member function.
Referenced Types
The OLE Proxy Wizard will recurse through type definitions looking for referenced types and making sure that all referenced types get predeclared (where necessary) and eventually fully defined. This means that (in theory at least) you should always end up with code that compiles and doesn't contain any unknown or unreferenced types. The possible danger here is that if you include proxy code from two different OLE servers in your application, it is possible to get duplicate symbol warnings from the linker if both servers reference types from the same third type library. For example the NetManage controls supplied with Borland's C++ Builder all reference types declared in a common library. In this situation it may be necessary to carry out some editing to remove duplicate definitions / declarations.
GUID's
The proxy wizard collects GUID definitions in one place near the beginning of the header file. Each application module should include <initguid.h> in one source module only, prior to the generated header file, in order to create instances of the GUID's. GUID's for coclasses are named IID_CoName and for interfaces are named IID_Name. Use the coclass GUID's for binding to an instance of the Server (in CoCreateObject or TAutoProxy::Bind), and the interface GUID's for calls to QueryInterface to find a specific interface. By default the generated .cpp file includes <initguid.h>.
Duplicate Identifiers
ActiveX controls were designed to be used from Visual Basic and their naming conventions often take little account of C++ type names. Whenever the generated code doesn’t compile first time, you should look for identifiers that conflict with others already in use. For example then MS Office 8 Object library contains several interfaces that have a property called "RGB". This conflicts with the windows macro RGB, and the only solution here is to rename the properties with some other identifier - "Color" for example. In other cases it may be possible (or even desirable) to use namespaces to solve the identifier conflict.
Class SafeArray<T> provides an encapsulation of the SAFEARRAY API and enables code generated with ProxyWiz to support automation properties and methods that make use of SAFEARRAY's. Note that class T must be a non reference type, or IUnknown*, IDispatch*, BSTR, or TAutoVal. Use short or long instead of int wherever possible.
Constructors:
SafeArray<T>();
Creates an empty array of type T
SafeArray<T>(unsigned long len);
Creates a one dimensional array of length len.
SafeArray<T>(unsigned long len, T* values);
Creates a one dimensional array of length len, and initialises the array with the values contained in values.
SafeArray<T>(unsigned int cDims, SAFEARRAYBOUND* bound)
Creates a multidimensional array with cDims dimensions, and bounds specified by bounds.
SafeArray<T>(const SafeArray<T>& s);
Copy constructor.
SafeArray<T>(const SAFEARRAY* p)
Copies the array p.
SafeArray<T>(const TAutoVal& Val)
Extracts and copies array data from Val.
unsigned short Dimentions();
Returns the number of dimensions in the array, must be at least one.
SAFEARRAYBOUND* Bound(unsigned short i);
Returns the bounds for a given dimension.
TAutoVal GetValue(long* indices)
Returns the value stored at indices, there must be as many indices as dimensions in the array.
void SetValue(long* indices, TAutoVal v)
Sets the value v at the position in the array specified by indices, there must be as many indices as dimensions.
SafeArrayElementRef<T> operator[](long i)
Returns a reference to one item in the array, the number of dimensions must be one.
operator SAFEARRAY*(); operator SAFEARRAY**();
Provides access to the underlying data, use when passing a SafeArray<T> to one of the windows API functions, or a COM interface.
supportproxywiz(at)armin-tueting.com
Please let me know if you find any bugs or have any suggestions, for bug reports, if possible please mail me a copy of the relevant type library. Make sure you have read the comments section above before labelling something as a bug!
Armin Tueting,
September 2009.
Release: v2.1 (Apr-2007), generate UNICODE.
Release: v2.2 (Jul-2007), processing command line arguments.
Release: v2.3 (Jan-2008), Vista compatibility, initialize with default values for Author, Company and Copyright from EXPERT.INI and better compatibility for BC5x.
Release: v3.0 (Sep-2009), general update.