<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <!-- /home/espenr/tmp/qt-3.2-espenr-29145/qt-x11-free-3.2.3/extensions/activeqt/doc/index.doc:52 --> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>The QAxServer Module</title> <style type="text/css"><!-- h3.fn,span.fn { margin-left: 1cm; text-indent: -1cm; } a:link { color: #004faf; text-decoration: none } a:visited { color: #672967; text-decoration: none } body { background: #ffffff; color: black; } --></style> </head> <body> <table border="0" cellpadding="0" cellspacing="0" width="100%"> <tr bgcolor="#E5E5E5"> <td valign=center> <a href="index.html"> <font color="#004faf">Home</font></a> | <a href="classes.html"> <font color="#004faf">All Classes</font></a> | <a href="mainclasses.html"> <font color="#004faf">Main Classes</font></a> | <a href="annotated.html"> <font color="#004faf">Annotated</font></a> | <a href="groups.html"> <font color="#004faf">Grouped Classes</font></a> | <a href="functions.html"> <font color="#004faf">Functions</font></a> </td> <td align="right" valign="center"><img src="logo32.png" align="right" width="64" height="32" border="0"></td></tr></table><h1 align=center>The QAxServer Module</h1> <p> <p> <!-- toc --> <ul> <li><a href="#1"> Introduction </a> <li><a href="#2"> Building the library </a> <li><a href="#3"> Using the library </a> <ul> <li><a href="#3-1"> Out-of-process vs. In-process </a> </ul> <li><a href="#4"> Implementing Controls </a> <ul> <li><a href="#4-1"> Data Types </a> <li><a href="#4-2"> Sub-Objects </a> <li><a href="#4-3"> Property Notification </a> </ul> <li><a href="#5"> Serving Controls </a> <li><a href="#6"> Using the Controls </a> <li><a href="#7"> Enhanced features </a> <ul> <li><a href="#7-1"> More Interfaces </a> <li><a href="#7-2"> Fewer methods and properties </a> </ul> </ul> <!-- endtoc --> <p> <h2> Introduction </h2> <a name="1"></a><p> The QAxServer module provides a static library implementing the functions required to turn a standard Qt binary into an ActiveX control server. <p> This module is part of the <a href="activeqt.html">ActiveQt framework</a>. (To incorporate ActiveX controls in a Qt application see the <a href="qaxcontainer.html">QAxContainer module</a>.) <p> The module consists of three classes <ul> <li> <a href="qaxfactory.html">QAxFactory</a> defines a factory for the creation of ActiveX components. <li> <a href="qaxbindable.html">QAxBindable</a> provides an interface between the Qt widget and the ActiveX control. <li> <a href="qaxaggregated.html">QAxAggregated</a> can be subclassed to implement additional COM interfaces. </ul> <p> Some <a href="qaxserver-examples.html">example implementations</a> of ActiveX controls are provided. <p> <h2> Building the library </h2> <a name="2"></a><p> In the <tt>activeqt</tt> directory (usually <tt>QTDIR/extensions/activeqt</tt>) enter the <tt>control</tt> subdirectory and run <tt>qmake</tt> to generate the makefile, and use the make tool (<tt>nmake</tt> for VC++, <tt>make</tt> for Borland) to build the library. The library <tt>qaxserver.lib</tt> will be linked into <tt>QTDIR/lib</tt>. <p> <h2> Using the library </h2> <a name="3"></a><p> To turn a standard Qt application into an ActiveX server using the QAxServer library you must add <tt>activeqt</tt> as a CONFIG setting in your <tt>.pro</tt> file. <p> An out-of-process executable server is generated from a <tt>.pro</tt> file like this: <pre> TEMPLATE = app CONFIG += qt activeqt RC_FILE = qaxserver.rc ... </pre> <p> To build an in-process server, use a <tt>.pro</tt> file like this: <pre> TEMPLATE = lib CONFIG += qt activeqt dll DEF_FILE = qaxserver.def RC_FILE = qaxserver.rc ... </pre> <p> The files <tt>qaxserver.rc</tt> and <tt>qaxserver.def</tt> are part of the framework and can be used from their usual location (specify a path in the <tt>.pro</tt> file), or copied into the project directory. You should <em>not</em> modify these files. <p> The <tt>activeqt</tt> configuration will cause the <tt>qmake</tt> tool to add the required build steps to the build system: <ul> <li> link the binary against <tt>qaxserver.lib</tt> <li> generate an interface definition and link the type library into the binary <li> register the server </ul> <p> See the <a href="qaxserver-faq.html">QAxServer FAQ</a> for a list of common problems when building the ActiveX server. <p> <h3> Out-of-process vs. In-process </h3> <a name="3-1"></a><p> Whether your ActiveX server should run as a stand-alone executable or as a shared library in the client process depends mainly on the type of controls you want to provide in the server. <p> An executable server has the advantage of being able to run as a stand-alone application, but adds considerable overhead to the communication between the ActiveX client and the control. If the control has a programming error only the server process running the control will crash, and the client application will probably continue to run. <p> An in-process server is usually smaller and has faster startup time. The communication between client and server is done directly through virtual function calls and does not introduce the overhead required for remote procedure calls. But if the server crashes the client application is likely to crash as well. <p> Both server types can use Qt either as a shared library, or statically linked into the server binary. <p> <h2> Implementing Controls </h2> <a name="4"></a><p> To implement an ActiveX control with Qt, create a subclass of <a href="qwidget.html">QWidget</a> or any existing QWidget subclass: <p> <pre> #include <<a href="qwidget-h.html">qwidget.h</a>> class MyActiveX : public <a href="qwidget.html">QWidget</a> { <a href="metaobjects.html#Q_OBJECT">Q_OBJECT</a> </pre> <p> The <a href="metaobjects.html#Q_OBJECT">Q_OBJECT</a> macro is required to provide the <a href="metaobjects.html#meta-object">meta object</a> information about the widget to the <a href="activeqt.html#ActiveQt">ActiveQt</a> framework. Use the <tt>Q_PROPERTY</tt> macro to declare properties for the ActiveX control: <p> <pre> Q_PROPERTY( int value READ value WRITE setValue ) </pre> <p> Declare a standard QWidget constructor taking a parent widget and a name, and functions, signals and slots like any normal QWidget. <a href="#footnote1"><sup>(1)</sup></a><a name="footnote-call1"></a> <p> <pre> public: MyActiveX( <a href="qwidget.html">QWidget</a> *parent = 0, const char *name = 0 ) ... int value() const; public slots: void setValue( int ); ... signals: void valueChange( int ); ... }; </pre> <p> The ActiveQt framework will expose properties and public slots as ActiveX properties and methods, and signals as ActiveX events, and convert between the Qt data types and the equivalent COM data types. <p> <h3> Data Types </h3> <a name="4-1"></a><p> The Qt data types that are supported for properties are: <p> <center><table cellpadding="4" cellspacing="2" border="0"> <tr bgcolor="#a2c511"> <th valign="top">Qt data type <th valign="top">COM property <tr bgcolor="#f0f0f0"> <td valign="top">bool <td valign="top">VARIANT_BOOL <tr bgcolor="#d0d0d0"> <td valign="top">QString <td valign="top">BSTR <tr bgcolor="#f0f0f0"> <td valign="top">QCString <td valign="top">BSTR <tr bgcolor="#d0d0d0"> <td valign="top">int <td valign="top">int <tr bgcolor="#f0f0f0"> <td valign="top">uint <td valign="top">unsigned int <tr bgcolor="#d0d0d0"> <td valign="top">double <td valign="top">double <tr bgcolor="#f0f0f0"> <td valign="top">Q_LLONG <td valign="top">CY <tr bgcolor="#d0d0d0"> <td valign="top">Q_ULLONG <td valign="top">CY <tr bgcolor="#f0f0f0"> <td valign="top">QColor <td valign="top">OLE_COLOR <tr bgcolor="#d0d0d0"> <td valign="top">QDate <td valign="top">DATE <tr bgcolor="#f0f0f0"> <td valign="top">QDateTime <td valign="top">DATE <tr bgcolor="#d0d0d0"> <td valign="top">QTime <td valign="top">DATE <tr bgcolor="#f0f0f0"> <td valign="top">QFont <td valign="top">IFontDisp* <tr bgcolor="#d0d0d0"> <td valign="top">QPixmap <td valign="top">IPictureDisp* <a href="#footnote2"><sup>(2)</sup></a><a name="footnote-call2"></a> <tr bgcolor="#f0f0f0"> <td valign="top">QVariant <td valign="top">VARIANT <tr bgcolor="#d0d0d0"> <td valign="top">QValueList<QVariant> <td valign="top">SAFEARRAY(VARIANT) <tr bgcolor="#f0f0f0"> <td valign="top">QByteArray <td valign="top">SAFEARRAY(BYTE) </table></center> <p> The Qt data types that are supported for parameters in signals and slots are: <center><table cellpadding="4" cellspacing="2" border="0"> <tr bgcolor="#a2c511"> <th valign="top">Qt data type <th valign="top">COM parameter <tr bgcolor="#d0d0d0"> <td valign="top">bool <td valign="top">[in] VARIANT_BOOL <tr bgcolor="#f0f0f0"> <td valign="top">bool& <td valign="top">[in, out] VARIANT_BOOL* <tr bgcolor="#d0d0d0"> <td valign="top">QString, const <a href="qstring.html">QString</a>& <td valign="top">[in] BSTR <tr bgcolor="#f0f0f0"> <td valign="top">QString& <td valign="top">[in, out] BSTR* <tr bgcolor="#d0d0d0"> <td valign="top">QCString, const <a href="qcstring.html">QCString</a>& <td valign="top">[in] BSTR <tr bgcolor="#f0f0f0"> <td valign="top">QString& <td valign="top">[in, out] BSTR* <tr bgcolor="#d0d0d0"> <td valign="top">int <td valign="top">[in] int <tr bgcolor="#f0f0f0"> <td valign="top">int& <td valign="top">[in,out] int <tr bgcolor="#d0d0d0"> <td valign="top">uint <td valign="top">[in] unsigned int <tr bgcolor="#f0f0f0"> <td valign="top">uint& <td valign="top">[in, out] unsigned int* <tr bgcolor="#d0d0d0"> <td valign="top">double <td valign="top">[in] double <tr bgcolor="#f0f0f0"> <td valign="top">double& <td valign="top">[in, out] double* <tr bgcolor="#d0d0d0"> <td valign="top">QColor, const <a href="qcolor.html">QColor</a>& <td valign="top">[in] OLE_COLOR <tr bgcolor="#f0f0f0"> <td valign="top">QColor& <td valign="top">[in, out] OLE_COLOR* <tr bgcolor="#d0d0d0"> <td valign="top">QDate, const <a href="qdate.html">QDate</a>& <td valign="top">[in] DATE <tr bgcolor="#f0f0f0"> <td valign="top">QDate& <td valign="top">[in, out] DATE* <tr bgcolor="#d0d0d0"> <td valign="top">QDateTime, const <a href="qdatetime.html">QDateTime</a>& <td valign="top">[in] DATE <tr bgcolor="#f0f0f0"> <td valign="top">QDateTime& <td valign="top">[in, out] DATE* <tr bgcolor="#d0d0d0"> <td valign="top">QFont, const <a href="qfont.html">QFont</a>& <td valign="top">[in] IFontDisp* <tr bgcolor="#f0f0f0"> <td valign="top">QFont& <td valign="top">[in, out] IFontDisp** <tr bgcolor="#d0d0d0"> <td valign="top">QPixmap, const <a href="qpixmap.html">QPixmap</a>& <td valign="top">[in] IPictureDisp* <tr bgcolor="#f0f0f0"> <td valign="top">QPixmap& <td valign="top">[in, out] IPictureDisp** <tr bgcolor="#d0d0d0"> <td valign="top">QValueList<QVariant>, const <a href="qvaluelist.html">QValueList</a><QVariant>& <td valign="top">[in] SAFEARRAY(VARIANT) <tr bgcolor="#f0f0f0"> <td valign="top">QValueList<QVariant>& <td valign="top">[in, out] SAFEARRAY(VARIANT)* <tr bgcolor="#d0d0d0"> <td valign="top">QByteArray, const <a href="qbytearray.html">QByteArray</a>& <td valign="top">[in] SAFEARRAY(BYTE) <tr bgcolor="#f0f0f0"> <td valign="top">QByteArray& <td valign="top">[in, out] SAFEARRAY(BYTE)* <tr bgcolor="#d0d0d0"> <td valign="top">QObject* <td valign="top">[in] IDispatch* </table></center> <p> Also supported are exported enums and sets (see Q_ENUMS and Q_SETS). The in-parameter types are also supported as return values. <p> Properties and signals/slots that have parameters using any other data types are ignored by the QActiveX framework. <p> <h3> Sub-Objects </h3> <a name="4-2"></a><p> COM objects can have multiple sub-objects that can represent a sub element of the COM object. A COM object representing a multi-document spread sheet application can for example provide one sub-object for each spread sheet. <p> Any <a href="qobject.html">QObject</a> subclass can be used as the type for a sub object in ActiveX. The <a href="qaxfactory.html">QAxFactory</a> implementation (see below) needs to return the classname of the sub type as one key in the featureList() implementation, as well as the IDs for the COM class, the interface and event interface of that type. Then the type can be used as e.g. the return value or paramter of a slot. <p> <h3> Property Notification </h3> <a name="4-3"></a><p> To make the properties bindable for the ActiveX client, use multiple inheritance from the <a href="qaxbindable.html">QAxBindable</a> class: <p> <pre> #include <qwidget.h> <b>#include <qaxbindable.h></b> class MyActiveX : public <a href="qwidget.html">QWidget</a><b>, public QAxBindable</b> { Q_OBJECT </pre> When implementing the property write functions, use the QAxBindable class's requestPropertyChange() and propertyChanged() functions to allow ActiveX clients to bind to the control properties. <a href="#footnote3"><sup>(3)</sup></a><a name="footnote-call3"></a> <p> <h2> Serving Controls </h2> <a name="5"></a><p> To make an ActiveX control available to the COM system it must be registered in the system registry using five unique identifiers. These identifiers are provided by tools like <tt>guidgen</tt> or <tt>uuidgen</tt>. The registration information allows COM to localize the binary providing a requested ActiveX control, marshall remote procedure calls to the control and read type information about the methods and properties exposed by the control. <p> To create the ActiveX control when the client asks for it the server must export an implementation of a <a href="qaxfactory.html">QAxFactory</a>. Use the default factory when the server provides only a single ActiveX control, and implement a subclass of QAxFactory to provide multiple ActiveX controls. The default factory is available through a macro that takes the identifiers COM requires to locate the ActiveX control on the target system: <p> <pre> QAXFACTORY_DEFAULT ( MyActiveX, "{ad90301a-849e-4e8b-9a91-0a6dc5f6461f}", "{87a5b65e-7fa9-4dc6-a176-47295988dcbd}", "{a6130ae9-8327-47ec-815b-d0b45a0d6e5e}", "{26c4e136-4e23-4347-af37-faf933b027e9}", "{a8f21901-7ff7-4f6a-b939-789620c03d83}" ) </pre> <p> The <a href="qaxfactory.html">QAxFactory class documentation</a> explains how to use this macro, and how to implement and use custom factories. <p> For out-of-process executable servers, implement a main() function, instantiate a <a href="qapplication.html">QApplication</a> object, and enter the event loop just like any normal Qt application. By default the application will start as a standard Qt application, but if you pass <tt>-activex</tt> on the command line it will start as an ActiveX server. Use <a href="qaxfactory.html#isServer">QAxFactory::isServer</a>() to create and run a standard application interface, or to prevent a stand-alone execution: <p> <pre> #include <qapplication.h> <b>#include <qaxfactory.h></b> int main( int argc, char **argv ) { QApplication app( argc, argv ); <b>if ( !QAxFactory::isServer() ) { // create and show main window... }</b> return app.exec(); } </pre> In-process servers must also implement <tt>main()</tt>; but it is never called so a dummy implementation is sufficient. <p> <pre> int main( int , char ** ) { return 0; } </pre> <p> To build the ActiveX server executable run <a href="qmake-manual.html">qmake</a> to generate the makefile, and use your compiler's make tool as for any other Qt application. The make process will also register the controls in the system registry by calling the resulting executable with the <tt>-regserver</tt> command line option. See the <a href="qaxserver-faq.html">Typical build errors</a> list for information on problems that can occur when building the ActiveQt server executable. <p> If the ActiveX server is an executable, the following command line options are supported: <center><table cellpadding="4" cellspacing="2" border="0"> <tr bgcolor="#a2c511"> <th valign="top">Option <th valign="top">Result <tr bgcolor="#f0f0f0"> <td valign="top"><tt>-regserver</tt> <td valign="top">Registers the server in the system registry <tr bgcolor="#d0d0d0"> <td valign="top"><tt>-unregserver</tt> <td valign="top">Unregisters the server from the system registry <tr bgcolor="#f0f0f0"> <td valign="top"><tt>-activex</tt> <td valign="top">Starts the application as an ActiveX server <tr bgcolor="#d0d0d0"> <td valign="top"><tt>-dumpidl <file></tt> <td valign="top">Writes the server's IDL to the specified file </table></center> <p> In-process servers can be registered using the <tt>regsvr32</tt> tool available on all Windows systems. <p> <h2> Using the Controls </h2> <a name="6"></a><p> To use the ActiveX controls, e.g. to embed them in a web page, use the <tt><object></tt> HTML tag. <p> <pre> <object ID="MyActiveX1" CLASSID="CLSID:ad90301a-849e-4e8b-9a91-0a6dc5f6461f"> ... <\object> </pre> <p> To initialize the control's properties, use <pre> <object ID=...> <param name="name" value="value"> <\object> </pre> <p> If the web browser supports scripting use JavaScript, VBScript and forms to script the control. The <a href="qaxserver-examples.html">examples</a> include demonstration HTML pages for the example controls. <p> <h2> Enhanced features </h2> <a name="7"></a><p> <h3> More Interfaces </h3> <a name="7-1"></a><p> The ActiveX control provide by ActiveQt servers supports a minimal set of COM interfaces to implement the OLE specifications. When the ActiveX class inherits from the <a href="qaxbindable.html">QAxBindable</a> class it can also implement additional COM interfaces. <p> Create a new subclass of <a href="qaxaggregated.html">QAxAggregated</a> and use multiple inheritance to subclass additional COM interface classes. <p> <pre> class AxImpl : public <a href="qaxaggregated.html">QAxAggregated</a>, public ISomeCOMInterface { public: AxImpl() {} long queryInterface( const <a href="quuid.html">QUuid</a> &iid, void **iface ) { *iface = 0; if ( iid == IID_ISomeCOMInterface ) *iface = (ISomeCOMInterface*)this; else return E_NOINTERFACE; AddRef(); return S_OK; } // IUnknown QAXAGG_IUNKNOWN // ISomeCOMInterface ... } </pre> <p> Reimplement the <tt>queryInterface()</tt> function to support the additional COM interfaces. <p> <pre> long AxImpl::queryInterface( const <a href="quuid.html">QUuid</a> &iid, void **iface ) { *iface = 0; if ( iid == IID_ISomeCOMInterface ) *iface = (ISomeCOMInterface*)this; else return E_NOINTERFACE; AddRef(); return S_OK; } </pre> <p> Since <tt>ISomeCOMInterface</tt> is a subclass of <tt>IUnknown</tt> you will have to implement the <tt>QueryInterface</tt>, <tt>AddRef</tt> and <tt>Release</tt> functions. Use the <tt>QAXAGG_IUNKNOWN</tt> macro in your class definition to do that. If you implement the IUnknown functions manually, delegate the calls to the interface pointer returned by the controllingUnknown() function, e.g. <pre> HRESULT AxImpl::QueryInterface( REFIID iid, void **iface ) { return controllingUnknown()->QueryInterface( iid, iface ); } </pre> Do not support the <tt>IUnknown</tt> interface itself in your <tt>queryInterface()</tt> implementation. <p> Implement the methods of the COM interfaces. If you need to make calls to the <a href="qwidget.html">QWidget</a> implementing the ActiveX control, use <a href="qaxaggregated.html#widget">QAxAggregated::widget</a>(). <p> In your <a href="qaxbindable.html">QAxBindable</a> subclass, implement <tt>createAggregate()</tt> to return a new object of the <a href="qaxaggregated.html">QAxAggregated</a> subclass. <p> <pre> class MyActiveX : public QWidget, <b>public QAxBindable</b> { Q_OBJECT public: MyActiveX( QWidget *parent, const char *name = 0 ); <b>QAxAggregated *createAggregate() { return new AxImpl(); } </b> }; </pre> <h3> Fewer methods and properties </h3> <a name="7-2"></a><p> By default all ActiveX controls expose not only their own methods and properties to ActiveX clients, but also those of all super classes, including QWidget. <p> This can be controlled by reimplementing <a href="qaxfactory.html">QAxFactory</a>'s exposeToSuperClass() function. Reimplement the function to return the last (furthest up the inheritance hierarchy) super class that should be exposed: <p> <pre> QString MyFactory::exposeToSuperClass( const <a href="qstring.html">QString</a> &key ) const { if ( key == "SmallActiveX" ) return key; return QAxFactory::exposeToSuperClass( key ); } </pre> <p> The SmallActiveX control will only expose its own functions and properties to clients, while all other ActiveX controls provided by this factory will expose their own functions and properties and also those of all their super classes including <a href="qwidget.html">QWidget</a>. The SmallActiveX class can of course propagate some of the QWidget functions and properties into its own interface. <hr> <ol> <li><a name="footnote1"></a> If a standard constructor is not present the compiler will issue an error "no overloaded function takes 2 parameters" when using the default factory through the <a href="qaxfactory.html#QAXFACTORY_DEFAULT">QAXFACTORY_DEFAULT</a> macro. If you cannot provide a standard constructor you must implement a <a href="qaxfactory.html">QAxFactory</a> custom factory and call the constructor you have in your implementation of QAxFactory::create. <a href="#footnote-call1">Back...</a> <li><a name="footnote2"></a> COM cannot marshal IPictureDisp accross process boundaries, so <a href="qpixmap.html">QPixmap</a> properties cannot be called for out-of-process servers. You can however marshal the image data via e.g. temporary files. See the Microsoft <a href="http://support.microsoft.com/default.aspx?scid=kb;[LN];Q150034">KB article Q150034</a> for more information. <a href="#footnote-call2">Back...</a> <li><a name="footnote3"></a> This is not required, but gives the client more control over the ActiveX control. <a href="#footnote-call3">Back...</a></ol> </hr> <!-- eof --> <p><address><hr><div align=center> <table width=100% cellspacing=0 border=0><tr> <td>Copyright © 2003 <a href="troll.html">Trolltech</a><td align=center><a href="trademarks.html">Trademarks</a> <td align=right><div align=right>Qt 3.2.3</div> </table></div></address></body> </html>