diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-07-10 15:24:15 -0500 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-07-10 15:24:15 -0500 |
commit | bd0f3345a938b35ce6a12f6150373b0955b8dd12 (patch) | |
tree | 7a520322212d48ebcb9fbe1087e7fca28b76185c /doc/html/qaxserver.html | |
download | qt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.tar.gz qt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.zip |
Add Qt3 development HEAD version
Diffstat (limited to 'doc/html/qaxserver.html')
-rw-r--r-- | doc/html/qaxserver.html | 1073 |
1 files changed, 1073 insertions, 0 deletions
diff --git a/doc/html/qaxserver.html b/doc/html/qaxserver.html new file mode 100644 index 0000000..73408d8 --- /dev/null +++ b/doc/html/qaxserver.html @@ -0,0 +1,1073 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<!-- /home/espenr/tmp/qt-3.3.8-espenr-2499/qt-x11-free-3.3.8/extensions/activeqt/doc/control.doc:1 --> +<html> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> +<title>The QAxServer Module</title> +<style type="text/css"><!-- +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"> The QAxServer build system +</a> +<ul> +<li><a href="#4-1"> Typical build problems +</a> +<ul> +<li><a href="#4-1-1"> Compiler errors +</a> +<ul> +<li><a href="#4-1-1-1"> "No overloaded function takes 2 parameters" +</a> +<li><a href="#4-1-1-2"> "syntax error: bad suffix on number" +</a> +</ul> +<li><a href="#4-1-2"> Linker errors +</a> +<ul> +<li><a href="#4-1-2-1"> "unresolved external symbol _ucm_instantiate" +</a> +<li><a href="#4-1-2-2"> "_ucm_initialize already defined in ..." +</a> +<li><a href="#4-1-2-3"> "cannot open file ... " +</a> +</ul> +<li><a href="#4-1-3"> Postprocessing and runtime errors +</a> +<ul> +<li><a href="#4-1-3-1"> The server executable crashes +</a> +<li><a href="#4-1-3-2"> The server executable is not a valid Win32 application +</a> +<li><a href="#4-1-3-3"> "Unable to Locate DLL" +</a> +<li><a href="#4-1-3-4"> The Server does not respond +</a> +<li><a href="#4-1-3-5"> The Object cannot be created +</a> +</ul> +</ul> +<li><a href="#4-2"> Debugging runtime errors +</a> +</ul> +<li><a href="#5"> Implementing Controls +</a> +<ul> +<li><a href="#5-1"> Data Types +</a> +<li><a href="#5-2"> Sub-Objects +</a> +<li><a href="#5-3"> Property Notification +</a> +</ul> +<li><a href="#6"> Serving Controls +</a> +<ul> +<li><a href="#6-1"> Distributing QAxServer binaries +</a> +<ul> +<li><a href="#6-1-1"> Installing stand-alone Servers +</a> +<li><a href="#6-1-2"> Installing In-process Servers +</a> +<li><a href="#6-1-3"> Distributing Servers over the Internet +</a> +</ul> +</ul> +<li><a href="#7"> Using the Controls +</a> +<ul> +<li><a href="#7-1"> Supported and Unsupported ActiveX clients +</a> +<ul> +<li><a href="#7-1-1"> Supported Clients +</a> +<li><a href="#7-1-2"> Unsupported Clients +</a> +</ul> +</ul> +<li><a href="#8"> Enhanced features +</a> +<ul> +<li><a href="#8-1"> Fewer methods and properties +</a> +<li><a href="#8-2"> Class Information and Tuning +</a> +<li><a href="#8-3"> Developing licensed components +</a> +<li><a href="#8-4"> More Interfaces +</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 can modify these files as long as it includes any file as the +type library entry, ie. you can add version information or use a +different toolbox icon. +<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> Additionally you can specify a version number using the <tt>VERSION</tt> +variable, e.g. +<pre> + TEMPLATE = lib + VERSION = 2.5 + ... + </pre> + +The version number specified will be used as the version of the type +library and of the server when registering. +<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> The QAxServer build system +</h2> +<a name="4"></a><p> To be able to build ActiveX controls with Qt, the build system +must be extended to include some additional build steps that are +used when the <tt>.pro</tt> file includes <tt>activeqt</tt> in the <tt>CONFIG</tt> +settings. The resulting makefile will: +<p> <ul> +<li> Link the executable against <tt>qaxserver.lib</tt> instead of <tt>qtmain.lib</tt> +<li> Call the resulting executable with the <tt>-dumpidl</tt> parameter to +generate an IDL description of the ActiveX controls provided by +the server. +<li> Compile the IDL into a type library using the MIDL tool +<li> Attach the resulting type library as a binary resource to the server +executable +</ul> +<p> Attaching resources to an executable is not supported by +Windows 95/98/ME, but a server built on +Windows NT/2000/XP will work on those versions. +<p> <h3> Typical build problems +</h3> +<a name="4-1"></a><p> The compiler/linker errors listed are based on those issued by the +Microsoft Visual C++ 6.0 compiler. +<p> <h4> Compiler errors +</h4> +<a name="4-1-1"></a><p> <h5> "No overloaded function takes 2 parameters" +</h5> +<a name="4-1-1-1"></a><p> When the error occurs in code that uses the <a href="qaxfactory.html#QAXFACTORY_DEFAULT">QAXFACTORY_DEFAULT</a> +macro, the widget class had no constructor that can be used by the +default factory. Either add a standard widget constructor or +implement a custom factory that doesn't require one. +<p> When the error occurs in code that uses the <a href="qaxfactory.html#QAXFACTORY_EXPORT">QAXFACTORY_EXPORT</a> +macro, the <a href="qaxfactory.html">QAxFactory</a> subclass had no appropriate constructor. +Provide a public class constructor like +<pre> + MyFactory( const <a href="quuid.html">QUuid</a> &, const <a href="quuid.html">QUuid</a> & ); + </pre> + +for your factory class. +<p> <h5> "syntax error: bad suffix on number" +</h5> +<a name="4-1-1-2"></a><p> The unique identifiers have not been passed as strings into the +<a href="qaxfactory.html#QAXFACTORY_EXPORT">QAXFACTORY_EXPORT</a> or <a href="qaxfactory.html#QAXFACTORY_DEFAULT">QAXFACTORY_DEFAULT</a> macro. +<p> <h4> Linker errors +</h4> +<a name="4-1-2"></a><p> <h5> "unresolved external symbol _ucm_instantiate" +</h5> +<a name="4-1-2-1"></a><p> The server does not export an implementation of a QAxFactory. Use +the <a href="qaxfactory.html#QAXFACTORY_EXPORT">QAXFACTORY_EXPORT</a> macro in one of the project's +implementation files to instantiate and export a factory, or use +the <a href="qaxfactory.html#QAXFACTORY_DEFAULT">QAXFACTORY_DEFAULT</a> macro to use the default factory. +<p> <h5> "_ucm_initialize already defined in ..." +</h5> +<a name="4-1-2-2"></a><p> The server exports more than one implementation of a <a href="qaxfactory.html">QAxFactory</a>, +or exports the same implementation twice. If you use the default +factory, the <a href="qaxfactory.html#QAXFACTORY_DEFAULT">QAXFACTORY_DEFAULT</a> macro must only be used once in +the project. Use a custom QAxFactory implementation and the <a href="qaxfactory.html#QAXFACTORY_EXPORT">QAXFACTORY_EXPORT</a> macro if the server provides multiple ActiveX +controls. +<p> <h5> "cannot open file ... " +</h5> +<a name="4-1-2-3"></a><p> The ActiveX server could not shut down properly when the last +client stopped using it. It usually takes about two seconds for +the application to terminate, but you might have to use the task +manager to kill the process (e.g. when a client doesn't release +the controls properly). +<p> <h4> Postprocessing and runtime errors +</h4> +<a name="4-1-3"></a><p> The <a href="activeqt.html#ActiveQt">ActiveQt</a> build system performs four commands after the linking +of the binary to make it into an ActiveX server. +<p> <ul> +<li> Call the server to dump the IDL for the controls +<li> Compile the IDL into a type library +<li> Attach the type library as a binary resource to the server +<li> Register the server +</ul> +<p> For this to work the server has to meet some requirements: +<p> <ul> +<li> All controls exposed can be created with nothing but a <a href="qapplication.html">QApplication</a> +instance being present +<li> The initial linking of the server includes a temporary type +library resource +<li> All dependencies required to run the server are in the system path +(or in the path used by the calling environment; note that Visual +Studio has it's own set of environment variables listed in the +Tools|Options|Directories dialog). +</ul> +<p> If those requirements are not met one ore more of the following +errors are likely to occure: +<p> <h5> The server executable crashes +</h5> +<a name="4-1-3-1"></a><p> To generate the IDL the widgets exposed as ActiveX controls need to +be instantiated (the constructor is called). At this point, nothing +else but a QApplication object exists. Your widget constructor must +not rely on any other objects to be created, e.g. it should check for +null-pointers. +<p> To debug your server run it with -dumpidl outputfile and check where +it crashes. +<p> Note that no functions of the control are called. +<p> <h5> The server executable is not a valid Win32 application +</h5> +<a name="4-1-3-2"></a><p> Attaching the type library corrupted the server binary. This is a +bug in Windows and happens only with release builds. +<p> The first linking step has to link a dummy type library into the +executable that can later be replaced by idc. Add a resource file +with a type library to your project as demonstrated in the examples. +<p> <h5> "Unable to Locate DLL" +</h5> +<a name="4-1-3-3"></a><p> The build system needs to run the server executable to generate +the interface definition, and to register the server. If a dynamic +link library the server links against is not in the path this +might fail (e.g. Visual Studio calls the server using the +enivronment settings specified in the "Directories" option). Make +sure that all DLLs required by your server are located in a +directory that is listed in the path as printed in the error +message box. +<p> <h5> The Server does not respond +</h5> +<a name="4-1-3-4"></a><p> If the system is unable to start the server (check with the task +manager whether the server runs a process), make sure that no DLL +the server depends on is missing from the system path (e.g. the Qt +DLL!). Use a dependency walker to view all dependencies of the server +binary. +<p> If the server runs (e.g. the task manager lists a process), see +the following section for information on debugging your server. +<p> <h5> The Object cannot be created +</h5> +<a name="4-1-3-5"></a><p> If the server could be built and registered correctly during the build +process, but the object cannot be initiliazed e.g. by the OLE/COM Object +Viewer application, make sure that no DLL the server depends on is +missing from the system path (e.g. the Qt DLL). Use a dependency walker +to view all dependencies of the server binary. +<p> If the server runs, see the following section for information on +debugging your server. +<p> <h3> Debugging runtime errors +</h3> +<a name="4-2"></a><p> To debug an in-process server in Visual Studio, set the server project +as the active project, and specify a client "executable for debug +session" in the project settings (e.g. use the ActiveX Test Container). +You can set breakpoints in your code, and also step into ActiveQt and +Qt code if you installed the debug version. +<p> To debug an executable server, run the application in a debugger +and start with the command line parameter "-activex". Then start +your client and create an instance of your ActiveX control. COM +will use the existing process for the next client trying to create +an ActiveX control. +<p> <h2> Implementing Controls +</h2> +<a name="5"></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 ActiveQt 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="5-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">QStringList +<td valign="top">SAFEARRAY(BSTR) +<tr bgcolor="#d0d0d0"> +<td valign="top">QByteArray +<td valign="top">SAFEARRAY(BYTE) +<tr bgcolor="#f0f0f0"> +<td valign="top">QRect +<td valign="top">User defined type +<tr bgcolor="#d0d0d0"> +<td valign="top">QSize +<td valign="top">User defined type +<tr bgcolor="#f0f0f0"> +<td valign="top">QPoint +<td valign="top">User defined type +</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">QStringList, const <a href="qstringlist.html">QStringList</a>& +<td valign="top">[in] SAFEARRAY(BSTR) +<tr bgcolor="#f0f0f0"> +<td valign="top">QStringList& +<td valign="top">[in, out] SAFEARRAY(BSTR)* +<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* +<tr bgcolor="#f0f0f0"> +<td valign="top">QRect& +<a href="#footnote3"><sup>(3)</sup></a><a name="footnote-call3"></a> +<td valign="top">[in, out] struct <a href="qrect.html">QRect</a> (user defined) +<tr bgcolor="#d0d0d0"> +<td valign="top">QSize& +<td valign="top">[in, out] struct <a href="qsize.html">QSize</a> (user defined) +<tr bgcolor="#f0f0f0"> +<td valign="top">QPoint& +<td valign="top">[in, out] struct <a href="qpoint.html">QPoint</a> (user defined) +</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="5-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="5-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="#footnote4"><sup>(4)</sup></a><a name="footnote-call4"></a> +<p> <h2> Serving Controls +</h2> +<a name="6"></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 you can implement a main() +function to 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> + +This is however not necessary as ActiveQt provides a default implementation +of a main function. The default implemenation calls <a href="qaxfactory.html#startServer">QAxFactory::startServer</a>(), +creates a QApplication instance and calls exec(). +<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. +<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="#d0d0d0"> <td valign="top"><tt>-regserver</tt> <td valign="top">Registers the server in the system registry +<tr bgcolor="#f0f0f0"> <td valign="top"><tt>-unregserver</tt> <td valign="top">Unregisters the server from the system registry +<tr bgcolor="#d0d0d0"> <td valign="top"><tt>-activex</tt> <td valign="top">Starts the application as an ActiveX server +<tr bgcolor="#f0f0f0"> <td valign="top"><tt>-dumpidl <file> -version x.y</tt> <td valign="top">Writes the server's IDL to the +specified file. The type library will have version x.y +</table></center> +<p> In-process servers can be registered using the <tt>regsvr32</tt> tool available +on all Windows systems. +<p> <h3> Distributing QAxServer binaries +</h3> +<a name="6-1"></a><p> ActiveX servers written with Qt can use Qt either as a shared +library, or have Qt linked statically into the binary. Both ways +will produce rather large packages (either the server binary +itself becomes large, or you have to ship the Qt DLL). +<p> <h4> Installing stand-alone Servers +</h4> +<a name="6-1-1"></a><p> When your ActiveX server can also run as a stand-alone application, +run the server executable with the <tt>-regserver</tt> command line +parameter after installing the executable on the target system. +After that the controls provided by the server will be available to +ActiveX clients. +<p> <h4> Installing In-process Servers +</h4> +<a name="6-1-2"></a><p> When your ActiveX server is part of an installation package, use the +<tt>regsvr32</tt> tool provided by Microsoft to register the controls on +the target system. If this tool is not present, load the DLL into +your installer process, resolve the <tt>DllRegisterServer</tt> symbol and +call the function: +<p> <pre> + HMODULE dll = LoadLibrary( "myserver.dll" ); + typedef HRESULT(__stdcall *DllRegisterServerProc)(); + DllRegisterServerProc DllRegisterServer = + (DllRegisterServerProc)GetProcAddress( dll, "DllRegisterServer" ); + + HRESULT res = E_FAIL; + if ( DllRegisterServer ) + res = DllRegisterServer(); + if ( res != S_OK ) + // error handling + </pre> + +<p> <h4> Distributing Servers over the Internet +</h4> +<a name="6-1-3"></a><p> If you want to use controls in your server in web-pages you need to +make the server available to the browser used to view your page, and +you need to specify the location of the server package in your page. +<p> To specify the location of a server, use the CODEBASE attribute in +the OBJECT tag of your web-site. The value can point to the server +file itself, to an <tt>INF</tt> file listing other files the server requires +(e.g. the Qt DLL), or a compressed <tt>CAB</tt> archive. +<p> INF and CAB files are documented in almost every book available about +ActiveX and COM programming as well as in the MSDN library and various +other Online resources. The examples include INF files that can be used +to build CAB archives: +<p> + +<pre> [version] + signature="$CHICAGO$" + AdvancedINF=2.0 + [Add.Code] + simpleax.exe=simpleax.exe + [simpleax.exe] + file-win32-x86=thiscab + clsid={DF16845C-92CD-4AAB-A982-EB9840E74669} + RegisterServer=yes +</pre> +<p> The CABARC tool from Microsoft can easily generate CAB archives: +<pre> cabarc N simpleax.cab simpleax.exe simple.inf </pre> + +<p> The INF files assume a static build of Qt, so no dependencies to other DLLs +are listed in the INF files. To distribute an ActiveX server depending on +DLLs you must add the dependencies, and provide the library files +with the archive. +<p> <h2> Using the Controls +</h2> +<a name="7"></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> <h3> Supported and Unsupported ActiveX clients +</h3> +<a name="7-1"></a><p> The following is largly based on our own experiements with ActiveX +controls and client applications, and is by no means complete. +<p> <h4> Supported Clients +</h4> +<a name="7-1-1"></a><p> These standard applications work with ActiveX controls developed with +ActiveQt. Note that some clients support only in-process controls. +<p> <ul> +<li> Internet Explorer +<li> Microsoft ActiveX Control Test Container +<li> Microsoft Visual Studio 6.0 +<li> Microsoft Visual Studio.NET/2003 +<li> Microsoft Visual Basic 6.0 +<li> MFC- and ATL-based containers +<li> Sybase PowerBuilder +<li> ActiveQt based containers +</ul> +<p> Microsoft Office applications are supported, but you need to register +the controls as "Insertable" objects. Reimplement <tt>QAxFactory::registerClass</tt> +to add this attribute to the COM class, or set the "Insertable" class info +for your class to "yes" using the Q_CLASSINFO macro. +<p> <h4> Unsupported Clients +</h4> +<a name="7-1-2"></a><p> We have not managed to make ActiveQt based COM objects work with the +following client applications. +<p> <ul> +<li> Borland C++ Builder (Versions 5 and 6) +<li> Borland Delphi +</ul> +<p> <h2> Enhanced features +</h2> +<a name="8"></a><p> <h3> Fewer methods and properties +</h3> +<a name="8-1"></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 <a href="qwidget.html">QWidget</a>. +<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 QWidget. The +SmallActiveX class can of course propagate some of the QWidget +functions and properties into its own interface. +<p> <h3> Class Information and Tuning +</h3> +<a name="8-2"></a><p> An alternative way to reimplementing QAxFactory to have more control +about how objects are registered or exposed is to provide class +specific information using the Q_CLASSINFO macro, which is part of +Qt's meta object system. +<p> <center><table cellpadding="4" cellspacing="2" border="0"> +<tr bgcolor="#a2c511"> +<th valign="top">Key +<th valign="top">Meaning of value +<tr bgcolor="#d0d0d0"> +<td valign="top">Version +<td valign="top">The version of the class (1.0 is default) +<tr bgcolor="#f0f0f0"> +<td valign="top">Description +<td valign="top">A string describing the class. +<tr bgcolor="#d0d0d0"> +<td valign="top">ClassID +<td valign="top">The class ID. +You must reimplement QAxFactory::classID if not specified. +<tr bgcolor="#f0f0f0"> +<td valign="top">InterfaceID +<td valign="top">The interface ID. +You must reimplement QAxFactory::interfaceID if not specified. +<tr bgcolor="#d0d0d0"> +<td valign="top">EventsID +<td valign="top">The event interface ID. +No signals are exposed as COM events if not specified. +<tr bgcolor="#f0f0f0"> +<td valign="top">DefaultProperty +<td valign="top">The property specified represents the default property of this class. +Ie. the default property of a push button would be "text". +<tr bgcolor="#d0d0d0"> +<td valign="top">DefaultSignal +<td valign="top">The signal specified respresents the default signal of this class. +Ie. the default signal of a push button would be "clicked". +<tr bgcolor="#f0f0f0"> +<td valign="top">LicenseKey +<td valign="top">Object creation requires the specified license key. The key can be +empty to require a licensed machine. By default classes are not +licensed. Also see the following section. +<tr bgcolor="#d0d0d0"> +<td valign="top">StockEvents +<td valign="top">Objects expose stock events if value is "yes". +See <a href="qaxfactory.html#hasStockEvents">QAxFactory::hasStockEvents</a>() +<tr bgcolor="#f0f0f0"> +<td valign="top">ToSuperClass +<td valign="top">Objects expose functionality of all super classes up to and +including the class name in value. +See <a href="qaxfactory.html#exposeToSuperClass">QAxFactory::exposeToSuperClass</a>() +<tr bgcolor="#d0d0d0"> +<td valign="top">Insertable +<td valign="top">If the value is "yes" the class is registered to be "Insertable" +and will be listed in OLE 2 containers (ie. Microsoft Office). This +attribute is not be set by default. +<tr bgcolor="#f0f0f0"> +<td valign="top">Aggregatable +<td valign="top">If the value is "no" the class does not support aggregation. By +default aggregation is supported. +<tr bgcolor="#d0d0d0"> +<td valign="top">Creatable +<td valign="top">If the value is "no" the class cannot be created by the client, +and is only available through the API of another class (ie. the +class is a sub-type). +<tr bgcolor="#f0f0f0"> +<td valign="top">RegisterObject +<td valign="top">If the value is "yes" objects of this class are registered with +OLE and accessible from the running object table (ie. clients +can connect to an already running instance of this class). This +attribute is only supported in out-of-process servers. +</table></center> +<p> Note that both keys and values are case sensitive. +<p> The following declares version 2.0 of a class that exposes only its +own API, and is available in the "Insert Objects" dialog of Microsoft +Office applications. +<p> + <pre> + class MyActiveX : public <a href="qwidget.html">QWidget</a> + { + Q_OBJECT + <b>Q_CLASSINFO("Version", "2.0") + Q_CLASSINFO("ClassID", "{7a4cffd8-cbcd-4ae9-ae7e-343e1e5710df}") + Q_CLASSINFO("InterfaceID", "{6fb035bf-8019-48d8-be51-ef05427d8994}") + Q_CLASSINFO("EventsID", "{c42fffdf-6557-47c9-817a-2da2228bc29c}") + Q_CLASSINFO("Insertable", "yes") + Q_CLASSINFO("ToSuperClass", "MyActiveX")</b> + + Q_PROPERTY( ... + public: + MyActiveX(QWidget *parent = 0, const char *name = 0); + + ... + }; + </pre> + +<h3> Developing licensed components +</h3> +<a name="8-3"></a><p> If you develop components you might want to control who is able to instantiate +those components. Since the server binary can be shipped to and registered on +any client machine it is possible for anybody to use those components in his +own software. +<p> Licensing components can be done using a variety of techniques, e.g. the code +creating the control can provide a license key, or the machine on which the +control is supposed to run needs to be licensed. +<p> To mark a Qt class as licensed specify a "LicenseKey" using the <tt>Q_CLASSINFO</tt> +macro. + + <pre> + class MyLicensedControl : public <a href="qwidget.html">QWidget</a> + { + Q_OBJECT + <b>Q_CLASSINFO("LicenseKey", "<key string>")</b> + ... + }; + </pre> + +The key is required to be able to create an instance of <tt>MyLicensedControl</tt> +on a machine that is not licensed itself. The licensed developer can now +redistributes the server binary with his application, which creates the control +using the value of "LicenseKey", while users of the application cannot create +the control without the license key. +<p> If a single license key for the control is not sufficient (ie. you want +differnet developers to receive different license keys) you can specify an +empty key to indicate that the control requires a license, and reimplement +<a href="qaxfactory.html#validateLicenseKey">QAxFactory::validateLicenseKey</a>() to verify that a license exists on the +system (ie. through a license file). +<p> <h3> More Interfaces +</h3> +<a name="8-4"></a><p> ActiveX controls provided by ActiveQt servers support 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 ); + + // 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, and use QAxAggregated::Object() +if you need to make calls to the <a href="qobject.html">QObject</a> subclass implementing the control. +<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 <a href="qwidget.html">QWidget</a>, + <b>public QAxBindable</b> + { + Q_OBJECT + public: + MyActiveX( QWidget *parent, const char *name = 0 ); + + <b>QAxAggregated *createAggregate() + { + return new AxImpl(); + } + </b> + }; + </pre> + +<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> + +OLE needs to marshal user defined types by reference (ByRef), and cannot +marshal them by value (ByVal). This is why const-references and object +parameters are not supported for <a href="qrect.html">QRect</a>, <a href="qsize.html">QSize</a> and <a href="qpoint.html">QPoint</a>. Also note that +servers with this datatype require Windows 98 or DCOM 1.2 to be installed. + <a href="#footnote-call3">Back...</a> <li><a name="footnote4"></a> + +This is not required, but gives the client more control over +the ActiveX control. + <a href="#footnote-call4">Back...</a></ol> +</hr> +<!-- eof --> +<p><address><hr><div align=center> +<table width=100% cellspacing=0 border=0><tr> +<td>Copyright © 2007 +<a href="troll.html">Trolltech</a><td align=center><a href="trademarks.html">Trademarks</a> +<td align=right><div align=right>Qt 3.3.8</div> +</table></div></address></body> +</html> |