| 1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | 
|---|
| 2 | <!-- /home/espenr/tmp/qt-3.3.8-espenr-2499/qt-x11-free-3.3.8/extensions/activeqt/doc/control.doc:1 --> | 
|---|
| 3 | <html> | 
|---|
| 4 | <head> | 
|---|
| 5 | <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> | 
|---|
| 6 | <title>The QAxServer Module</title> | 
|---|
| 7 | <style type="text/css"><!-- | 
|---|
| 8 | fn { margin-left: 1cm; text-indent: -1cm; } | 
|---|
| 9 | a:link { color: #004faf; text-decoration: none } | 
|---|
| 10 | a:visited { color: #672967; text-decoration: none } | 
|---|
| 11 | body { background: #ffffff; color: black; } | 
|---|
| 12 | --></style> | 
|---|
| 13 | </head> | 
|---|
| 14 | <body> | 
|---|
| 15 |  | 
|---|
| 16 | <table border="0" cellpadding="0" cellspacing="0" width="100%"> | 
|---|
| 17 | <tr bgcolor="#E5E5E5"> | 
|---|
| 18 | <td valign=center> | 
|---|
| 19 | <a href="index.html"> | 
|---|
| 20 | <font color="#004faf">Home</font></a> | 
|---|
| 21 | | <a href="classes.html"> | 
|---|
| 22 | <font color="#004faf">All Classes</font></a> | 
|---|
| 23 | | <a href="mainclasses.html"> | 
|---|
| 24 | <font color="#004faf">Main Classes</font></a> | 
|---|
| 25 | | <a href="annotated.html"> | 
|---|
| 26 | <font color="#004faf">Annotated</font></a> | 
|---|
| 27 | | <a href="groups.html"> | 
|---|
| 28 | <font color="#004faf">Grouped Classes</font></a> | 
|---|
| 29 | | <a href="functions.html"> | 
|---|
| 30 | <font color="#004faf">Functions</font></a> | 
|---|
| 31 | </td> | 
|---|
| 32 | <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> | 
|---|
| 33 |  | 
|---|
| 34 |  | 
|---|
| 35 | <p> | 
|---|
| 36 | <p> <!-- toc --> | 
|---|
| 37 | <ul> | 
|---|
| 38 | <li><a href="#1"> Introduction | 
|---|
| 39 | </a> | 
|---|
| 40 | <li><a href="#2"> Building the library | 
|---|
| 41 | </a> | 
|---|
| 42 | <li><a href="#3"> Using the library | 
|---|
| 43 | </a> | 
|---|
| 44 | <ul> | 
|---|
| 45 | <li><a href="#3-1"> Out-of-process vs. In-process | 
|---|
| 46 | </a> | 
|---|
| 47 | </ul> | 
|---|
| 48 | <li><a href="#4"> The QAxServer build system | 
|---|
| 49 | </a> | 
|---|
| 50 | <ul> | 
|---|
| 51 | <li><a href="#4-1"> Typical build problems | 
|---|
| 52 | </a> | 
|---|
| 53 | <ul> | 
|---|
| 54 | <li><a href="#4-1-1"> Compiler errors | 
|---|
| 55 | </a> | 
|---|
| 56 | <ul> | 
|---|
| 57 | <li><a href="#4-1-1-1"> "No overloaded function takes 2 parameters" | 
|---|
| 58 | </a> | 
|---|
| 59 | <li><a href="#4-1-1-2"> "syntax error: bad suffix on number" | 
|---|
| 60 | </a> | 
|---|
| 61 | </ul> | 
|---|
| 62 | <li><a href="#4-1-2"> Linker errors | 
|---|
| 63 | </a> | 
|---|
| 64 | <ul> | 
|---|
| 65 | <li><a href="#4-1-2-1"> "unresolved external symbol _ucm_instantiate" | 
|---|
| 66 | </a> | 
|---|
| 67 | <li><a href="#4-1-2-2"> "_ucm_initialize already defined in ..." | 
|---|
| 68 | </a> | 
|---|
| 69 | <li><a href="#4-1-2-3"> "cannot open file ... " | 
|---|
| 70 | </a> | 
|---|
| 71 | </ul> | 
|---|
| 72 | <li><a href="#4-1-3"> Postprocessing and runtime errors | 
|---|
| 73 | </a> | 
|---|
| 74 | <ul> | 
|---|
| 75 | <li><a href="#4-1-3-1"> The server executable crashes | 
|---|
| 76 | </a> | 
|---|
| 77 | <li><a href="#4-1-3-2"> The server executable is not a valid Win32 application | 
|---|
| 78 | </a> | 
|---|
| 79 | <li><a href="#4-1-3-3"> "Unable to Locate DLL" | 
|---|
| 80 | </a> | 
|---|
| 81 | <li><a href="#4-1-3-4"> The Server does not respond | 
|---|
| 82 | </a> | 
|---|
| 83 | <li><a href="#4-1-3-5"> The Object cannot be created | 
|---|
| 84 | </a> | 
|---|
| 85 | </ul> | 
|---|
| 86 | </ul> | 
|---|
| 87 | <li><a href="#4-2"> Debugging runtime errors | 
|---|
| 88 | </a> | 
|---|
| 89 | </ul> | 
|---|
| 90 | <li><a href="#5"> Implementing Controls | 
|---|
| 91 | </a> | 
|---|
| 92 | <ul> | 
|---|
| 93 | <li><a href="#5-1"> Data Types | 
|---|
| 94 | </a> | 
|---|
| 95 | <li><a href="#5-2"> Sub-Objects | 
|---|
| 96 | </a> | 
|---|
| 97 | <li><a href="#5-3"> Property Notification | 
|---|
| 98 | </a> | 
|---|
| 99 | </ul> | 
|---|
| 100 | <li><a href="#6"> Serving Controls | 
|---|
| 101 | </a> | 
|---|
| 102 | <ul> | 
|---|
| 103 | <li><a href="#6-1"> Distributing QAxServer binaries | 
|---|
| 104 | </a> | 
|---|
| 105 | <ul> | 
|---|
| 106 | <li><a href="#6-1-1"> Installing stand-alone Servers | 
|---|
| 107 | </a> | 
|---|
| 108 | <li><a href="#6-1-2"> Installing In-process Servers | 
|---|
| 109 | </a> | 
|---|
| 110 | <li><a href="#6-1-3"> Distributing Servers over the Internet | 
|---|
| 111 | </a> | 
|---|
| 112 | </ul> | 
|---|
| 113 | </ul> | 
|---|
| 114 | <li><a href="#7"> Using the Controls | 
|---|
| 115 | </a> | 
|---|
| 116 | <ul> | 
|---|
| 117 | <li><a href="#7-1"> Supported and Unsupported ActiveX clients | 
|---|
| 118 | </a> | 
|---|
| 119 | <ul> | 
|---|
| 120 | <li><a href="#7-1-1"> Supported Clients | 
|---|
| 121 | </a> | 
|---|
| 122 | <li><a href="#7-1-2"> Unsupported Clients | 
|---|
| 123 | </a> | 
|---|
| 124 | </ul> | 
|---|
| 125 | </ul> | 
|---|
| 126 | <li><a href="#8"> Enhanced features | 
|---|
| 127 | </a> | 
|---|
| 128 | <ul> | 
|---|
| 129 | <li><a href="#8-1"> Fewer methods and properties | 
|---|
| 130 | </a> | 
|---|
| 131 | <li><a href="#8-2"> Class Information and Tuning | 
|---|
| 132 | </a> | 
|---|
| 133 | <li><a href="#8-3"> Developing licensed components | 
|---|
| 134 | </a> | 
|---|
| 135 | <li><a href="#8-4"> More Interfaces | 
|---|
| 136 | </a> | 
|---|
| 137 | </ul> | 
|---|
| 138 | </ul> | 
|---|
| 139 | <!-- endtoc --> | 
|---|
| 140 |  | 
|---|
| 141 | <p> <h2> Introduction | 
|---|
| 142 | </h2> | 
|---|
| 143 | <a name="1"></a><p> The QAxServer module provides a static library implementing the | 
|---|
| 144 | functions required to turn a standard Qt binary into an ActiveX | 
|---|
| 145 | control server. | 
|---|
| 146 | <p> This module is part of the <a href="activeqt.html">ActiveQt | 
|---|
| 147 | framework</a>. (To incorporate ActiveX controls in a Qt | 
|---|
| 148 | application see the <a href="qaxcontainer.html">QAxContainer | 
|---|
| 149 | module</a>.) | 
|---|
| 150 | <p> The module consists of three classes | 
|---|
| 151 | <ul> | 
|---|
| 152 | <li> <a href="qaxfactory.html">QAxFactory</a> defines a factory for the creation of ActiveX components. | 
|---|
| 153 | <li> <a href="qaxbindable.html">QAxBindable</a> provides an interface between the Qt widget and the | 
|---|
| 154 | ActiveX control. | 
|---|
| 155 | <li> <a href="qaxaggregated.html">QAxAggregated</a> can be subclassed to implement additional COM interfaces. | 
|---|
| 156 | </ul> | 
|---|
| 157 | <p> Some <a href="qaxserver-examples.html">example implementations</a> | 
|---|
| 158 | of ActiveX controls are provided. | 
|---|
| 159 | <p> <h2> Building the library | 
|---|
| 160 | </h2> | 
|---|
| 161 | <a name="2"></a><p> In the <tt>activeqt</tt> directory (usually <tt>QTDIR/extensions/activeqt</tt>) | 
|---|
| 162 | enter the <tt>control</tt> subdirectory and run <tt>qmake</tt> to generate the | 
|---|
| 163 | makefile, and use the make tool (<tt>nmake</tt> for VC++, <tt>make</tt> for Borland) | 
|---|
| 164 | to build the library. The library <tt>qaxserver.lib</tt> will be linked into | 
|---|
| 165 | <tt>QTDIR/lib</tt>. | 
|---|
| 166 | <p> <h2> Using the library | 
|---|
| 167 | </h2> | 
|---|
| 168 | <a name="3"></a><p> To turn a standard Qt application into an ActiveX server using the | 
|---|
| 169 | QAxServer library you must add <tt>activeqt</tt> as a CONFIG setting | 
|---|
| 170 | in your <tt>.pro</tt> file. | 
|---|
| 171 | <p> An out-of-process executable server is generated from a <tt>.pro</tt> | 
|---|
| 172 | file like this: | 
|---|
| 173 | <pre> | 
|---|
| 174 | TEMPLATE = app | 
|---|
| 175 | CONFIG  += qt activeqt | 
|---|
| 176 |  | 
|---|
| 177 | RC_FILE  = qaxserver.rc | 
|---|
| 178 | ... | 
|---|
| 179 | </pre> | 
|---|
| 180 |  | 
|---|
| 181 | <p> To build an in-process server, use a <tt>.pro</tt> file like this: | 
|---|
| 182 | <pre> | 
|---|
| 183 | TEMPLATE = lib | 
|---|
| 184 | CONFIG  += qt activeqt dll | 
|---|
| 185 |  | 
|---|
| 186 | DEF_FILE = qaxserver.def | 
|---|
| 187 | RC_FILE  = qaxserver.rc | 
|---|
| 188 | ... | 
|---|
| 189 | </pre> | 
|---|
| 190 |  | 
|---|
| 191 | <p> The files <tt>qaxserver.rc</tt> and <tt>qaxserver.def</tt> are part of the | 
|---|
| 192 | framework and can be used from their usual location (specify a | 
|---|
| 193 | path in the <tt>.pro</tt> file), or copied into the project directory. | 
|---|
| 194 | You can modify these files as long as it includes any file as the | 
|---|
| 195 | type library entry, ie. you can add version information or use a | 
|---|
| 196 | different toolbox icon. | 
|---|
| 197 | <p> The <tt>activeqt</tt> configuration will cause the <tt>qmake</tt> tool to add the | 
|---|
| 198 | required build steps to the build system: | 
|---|
| 199 | <ul> | 
|---|
| 200 | <li> link the binary against <tt>qaxserver.lib</tt> | 
|---|
| 201 | <li> generate an interface definition and link the type library into | 
|---|
| 202 | the binary | 
|---|
| 203 | <li> register the server | 
|---|
| 204 | </ul> | 
|---|
| 205 | <p> Additionally you can specify a version number using the <tt>VERSION</tt> | 
|---|
| 206 | variable, e.g. | 
|---|
| 207 | <pre> | 
|---|
| 208 | TEMPLATE = lib | 
|---|
| 209 | VERSION = 2.5 | 
|---|
| 210 | ... | 
|---|
| 211 | </pre> | 
|---|
| 212 |  | 
|---|
| 213 | The version number specified will be used as the version of the type | 
|---|
| 214 | library and of the server when registering. | 
|---|
| 215 | <p> <h3> Out-of-process vs. In-process | 
|---|
| 216 | </h3> | 
|---|
| 217 | <a name="3-1"></a><p> Whether your ActiveX server should run as a stand-alone executable | 
|---|
| 218 | or as a shared library in the client process depends mainly on the | 
|---|
| 219 | type of controls you want to provide in the server. | 
|---|
| 220 | <p> An executable server has the advantage of being able to run as a | 
|---|
| 221 | stand-alone application, but adds considerable overhead to the | 
|---|
| 222 | communication between the ActiveX client and the control. If the | 
|---|
| 223 | control has a programming error only the server process running | 
|---|
| 224 | the control will crash, and the client application will probably | 
|---|
| 225 | continue to run. | 
|---|
| 226 | <p> An in-process server is usually smaller and has faster startup | 
|---|
| 227 | time. The communication between client and server is done directly | 
|---|
| 228 | through virtual function calls and does not introduce the overhead | 
|---|
| 229 | required for remote procedure calls. But if the server crashes the | 
|---|
| 230 | client application is likely to crash as well. | 
|---|
| 231 | <p> Both server types can use Qt either as a shared library, or | 
|---|
| 232 | statically linked into the server binary. | 
|---|
| 233 | <p> <h2> The QAxServer build system | 
|---|
| 234 | </h2> | 
|---|
| 235 | <a name="4"></a><p> To be able to build ActiveX controls with Qt, the build system | 
|---|
| 236 | must be extended to include some additional build steps that are | 
|---|
| 237 | used when the <tt>.pro</tt> file includes <tt>activeqt</tt> in the <tt>CONFIG</tt> | 
|---|
| 238 | settings. The resulting makefile will: | 
|---|
| 239 | <p> <ul> | 
|---|
| 240 | <li> Link the executable against <tt>qaxserver.lib</tt> instead of <tt>qtmain.lib</tt> | 
|---|
| 241 | <li> Call the resulting executable with the <tt>-dumpidl</tt> parameter to | 
|---|
| 242 | generate an IDL description of the ActiveX controls provided by | 
|---|
| 243 | the server. | 
|---|
| 244 | <li> Compile the IDL into a type library using the MIDL tool | 
|---|
| 245 | <li> Attach the resulting type library as a binary resource to the server | 
|---|
| 246 | executable | 
|---|
| 247 | </ul> | 
|---|
| 248 | <p> Attaching resources to an executable is not supported by | 
|---|
| 249 | Windows 95/98/ME, but a server built on | 
|---|
| 250 | Windows NT/2000/XP will work on those versions. | 
|---|
| 251 | <p> <h3> Typical build problems | 
|---|
| 252 | </h3> | 
|---|
| 253 | <a name="4-1"></a><p> The compiler/linker errors listed are based on those issued by the | 
|---|
| 254 | Microsoft Visual C++ 6.0 compiler. | 
|---|
| 255 | <p> <h4> Compiler errors | 
|---|
| 256 | </h4> | 
|---|
| 257 | <a name="4-1-1"></a><p> <h5> "No overloaded function takes 2 parameters" | 
|---|
| 258 | </h5> | 
|---|
| 259 | <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> | 
|---|
| 260 | macro, the widget class had no constructor that can be used by the | 
|---|
| 261 | default factory. Either add a standard widget constructor or | 
|---|
| 262 | implement a custom factory that doesn't require one. | 
|---|
| 263 | <p> When the error occurs in code that uses the <a href="qaxfactory.html#QAXFACTORY_EXPORT">QAXFACTORY_EXPORT</a> | 
|---|
| 264 | macro, the <a href="qaxfactory.html">QAxFactory</a> subclass had no appropriate constructor. | 
|---|
| 265 | Provide a public class constructor like | 
|---|
| 266 | <pre> | 
|---|
| 267 | MyFactory( const <a href="quuid.html">QUuid</a> &, const <a href="quuid.html">QUuid</a> & ); | 
|---|
| 268 | </pre> | 
|---|
| 269 |  | 
|---|
| 270 | for your factory class. | 
|---|
| 271 | <p> <h5> "syntax error: bad suffix on number" | 
|---|
| 272 | </h5> | 
|---|
| 273 | <a name="4-1-1-2"></a><p> The unique identifiers have not been passed as strings into the | 
|---|
| 274 | <a href="qaxfactory.html#QAXFACTORY_EXPORT">QAXFACTORY_EXPORT</a> or <a href="qaxfactory.html#QAXFACTORY_DEFAULT">QAXFACTORY_DEFAULT</a> macro. | 
|---|
| 275 | <p> <h4> Linker errors | 
|---|
| 276 | </h4> | 
|---|
| 277 | <a name="4-1-2"></a><p> <h5> "unresolved external symbol _ucm_instantiate" | 
|---|
| 278 | </h5> | 
|---|
| 279 | <a name="4-1-2-1"></a><p> The server does not export an implementation of a QAxFactory. Use | 
|---|
| 280 | the <a href="qaxfactory.html#QAXFACTORY_EXPORT">QAXFACTORY_EXPORT</a> macro in one of the project's | 
|---|
| 281 | implementation files to instantiate and export a factory, or use | 
|---|
| 282 | the <a href="qaxfactory.html#QAXFACTORY_DEFAULT">QAXFACTORY_DEFAULT</a> macro to use the default factory. | 
|---|
| 283 | <p> <h5> "_ucm_initialize already defined in ..." | 
|---|
| 284 | </h5> | 
|---|
| 285 | <a name="4-1-2-2"></a><p> The server exports more than one implementation of a <a href="qaxfactory.html">QAxFactory</a>, | 
|---|
| 286 | or exports the same implementation twice. If you use the default | 
|---|
| 287 | factory, the <a href="qaxfactory.html#QAXFACTORY_DEFAULT">QAXFACTORY_DEFAULT</a> macro must only be used once in | 
|---|
| 288 | 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 | 
|---|
| 289 | controls. | 
|---|
| 290 | <p> <h5> "cannot open file ... " | 
|---|
| 291 | </h5> | 
|---|
| 292 | <a name="4-1-2-3"></a><p> The ActiveX server could not shut down properly when the last | 
|---|
| 293 | client stopped using it. It usually takes about two seconds for | 
|---|
| 294 | the application to terminate, but you might have to use the task | 
|---|
| 295 | manager to kill the process (e.g. when a client doesn't release | 
|---|
| 296 | the controls properly). | 
|---|
| 297 | <p> <h4> Postprocessing and runtime errors | 
|---|
| 298 | </h4> | 
|---|
| 299 | <a name="4-1-3"></a><p> The <a href="activeqt.html#ActiveQt">ActiveQt</a> build system performs four commands after the linking | 
|---|
| 300 | of the binary to make it into an ActiveX server. | 
|---|
| 301 | <p> <ul> | 
|---|
| 302 | <li> Call the server to dump the IDL for the controls | 
|---|
| 303 | <li> Compile the IDL into a type library | 
|---|
| 304 | <li> Attach the type library as a binary resource to the server | 
|---|
| 305 | <li> Register the server | 
|---|
| 306 | </ul> | 
|---|
| 307 | <p> For this to work the server has to meet some requirements: | 
|---|
| 308 | <p> <ul> | 
|---|
| 309 | <li> All controls exposed can be created with nothing but a <a href="qapplication.html">QApplication</a> | 
|---|
| 310 | instance being present | 
|---|
| 311 | <li> The initial linking of the server includes a temporary type | 
|---|
| 312 | library resource | 
|---|
| 313 | <li> All dependencies required to run the server are in the system path | 
|---|
| 314 | (or in the path used by the calling environment; note that Visual | 
|---|
| 315 | Studio has it's own set of environment variables listed in the | 
|---|
| 316 | Tools|Options|Directories dialog). | 
|---|
| 317 | </ul> | 
|---|
| 318 | <p> If those requirements are not met one ore more of the following | 
|---|
| 319 | errors are likely to occure: | 
|---|
| 320 | <p> <h5> The server executable crashes | 
|---|
| 321 | </h5> | 
|---|
| 322 | <a name="4-1-3-1"></a><p> To generate the IDL the widgets exposed as ActiveX controls need to | 
|---|
| 323 | be instantiated (the constructor is called). At this point, nothing | 
|---|
| 324 | else but a QApplication object exists. Your widget constructor must | 
|---|
| 325 | not rely on any other objects to be created, e.g. it should check for | 
|---|
| 326 | null-pointers. | 
|---|
| 327 | <p> To debug your server run it with -dumpidl outputfile and check where | 
|---|
| 328 | it crashes. | 
|---|
| 329 | <p> Note that no functions of the control are called. | 
|---|
| 330 | <p> <h5> The server executable is not a valid Win32 application | 
|---|
| 331 | </h5> | 
|---|
| 332 | <a name="4-1-3-2"></a><p> Attaching the type library corrupted the server binary. This is a | 
|---|
| 333 | bug in Windows and happens only with release builds. | 
|---|
| 334 | <p> The first linking step has to link a dummy type library into the | 
|---|
| 335 | executable that can later be replaced by idc. Add a resource file | 
|---|
| 336 | with a type library to your project as demonstrated in the examples. | 
|---|
| 337 | <p> <h5> "Unable to Locate DLL" | 
|---|
| 338 | </h5> | 
|---|
| 339 | <a name="4-1-3-3"></a><p> The build system needs to run the server executable to generate | 
|---|
| 340 | the interface definition, and to register the server. If a dynamic | 
|---|
| 341 | link library the server links against is not in the path this | 
|---|
| 342 | might fail (e.g. Visual Studio calls the server using the | 
|---|
| 343 | enivronment settings specified in the "Directories" option). Make | 
|---|
| 344 | sure that all DLLs required by your server are located in a | 
|---|
| 345 | directory that is listed in the path as printed in the error | 
|---|
| 346 | message box. | 
|---|
| 347 | <p> <h5> The Server does not respond | 
|---|
| 348 | </h5> | 
|---|
| 349 | <a name="4-1-3-4"></a><p> If the system is unable to start the server (check with the task | 
|---|
| 350 | manager whether the server runs a process), make sure that no DLL | 
|---|
| 351 | the server depends on is missing from the system path (e.g. the Qt | 
|---|
| 352 | DLL!). Use a dependency walker to view all dependencies of the server | 
|---|
| 353 | binary. | 
|---|
| 354 | <p> If the server runs (e.g. the task manager lists a process), see | 
|---|
| 355 | the following section for information on debugging your server. | 
|---|
| 356 | <p> <h5> The Object cannot be created | 
|---|
| 357 | </h5> | 
|---|
| 358 | <a name="4-1-3-5"></a><p> If the server could be built and registered correctly during the build | 
|---|
| 359 | process, but the object cannot be initiliazed e.g. by the OLE/COM Object | 
|---|
| 360 | Viewer application, make sure that no DLL the server depends on is | 
|---|
| 361 | missing from the system path (e.g. the Qt DLL). Use a dependency walker | 
|---|
| 362 | to view all dependencies of the server binary. | 
|---|
| 363 | <p> If the server runs, see the following section for information on | 
|---|
| 364 | debugging your server. | 
|---|
| 365 | <p> <h3> Debugging runtime errors | 
|---|
| 366 | </h3> | 
|---|
| 367 | <a name="4-2"></a><p> To debug an in-process server in Visual Studio, set the server project | 
|---|
| 368 | as the active project, and specify a client "executable for debug | 
|---|
| 369 | session" in the project settings (e.g. use the ActiveX Test Container). | 
|---|
| 370 | You can set breakpoints in your code, and also step into ActiveQt and | 
|---|
| 371 | Qt code if you installed the debug version. | 
|---|
| 372 | <p> To debug an executable server, run the application in a debugger | 
|---|
| 373 | and start with the command line parameter "-activex". Then start | 
|---|
| 374 | your client and create an instance of your ActiveX control. COM | 
|---|
| 375 | will use the existing process for the next client trying to create | 
|---|
| 376 | an ActiveX control. | 
|---|
| 377 | <p> <h2> Implementing Controls | 
|---|
| 378 | </h2> | 
|---|
| 379 | <a name="5"></a><p> To implement an ActiveX control with Qt, create a subclass of <a href="qwidget.html">QWidget</a> | 
|---|
| 380 | or any existing QWidget subclass: | 
|---|
| 381 | <p> <pre> | 
|---|
| 382 | #include <<a href="qwidget-h.html">qwidget.h</a>> | 
|---|
| 383 |  | 
|---|
| 384 | class MyActiveX : public <a href="qwidget.html">QWidget</a> | 
|---|
| 385 | { | 
|---|
| 386 | <a href="metaobjects.html#Q_OBJECT">Q_OBJECT</a> | 
|---|
| 387 | </pre> | 
|---|
| 388 |  | 
|---|
| 389 | <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 | 
|---|
| 390 | about the widget to the ActiveQt framework. | 
|---|
| 391 | Use the <tt>Q_PROPERTY</tt> macro to declare properties for the ActiveX control: | 
|---|
| 392 | <p> <pre> | 
|---|
| 393 | Q_PROPERTY( int value READ value WRITE setValue ) | 
|---|
| 394 | </pre> | 
|---|
| 395 |  | 
|---|
| 396 | <p> Declare a standard QWidget constructor taking a parent widget and a name, | 
|---|
| 397 | and functions, signals and slots like any normal QWidget. | 
|---|
| 398 | <a href="#footnote1"><sup>(1)</sup></a><a name="footnote-call1"></a> | 
|---|
| 399 | <p> <pre> | 
|---|
| 400 | public: | 
|---|
| 401 | MyActiveX( <a href="qwidget.html">QWidget</a> *parent = 0, const char *name = 0 ) | 
|---|
| 402 | ... | 
|---|
| 403 |  | 
|---|
| 404 | int value() const; | 
|---|
| 405 |  | 
|---|
| 406 | public slots: | 
|---|
| 407 | void setValue( int ); | 
|---|
| 408 | ... | 
|---|
| 409 |  | 
|---|
| 410 | signals: | 
|---|
| 411 | void valueChange( int ); | 
|---|
| 412 | ... | 
|---|
| 413 |  | 
|---|
| 414 | }; | 
|---|
| 415 | </pre> | 
|---|
| 416 |  | 
|---|
| 417 | <p> The ActiveQt framework will expose properties and public slots as ActiveX | 
|---|
| 418 | properties and methods, and signals as ActiveX events, and convert between | 
|---|
| 419 | the Qt data types and the equivalent COM data types. | 
|---|
| 420 | <p> <h3> Data Types | 
|---|
| 421 | </h3> | 
|---|
| 422 | <a name="5-1"></a><p> The Qt data types that are supported for properties are: | 
|---|
| 423 | <p> <center><table cellpadding="4" cellspacing="2" border="0"> | 
|---|
| 424 | <tr bgcolor="#a2c511"> | 
|---|
| 425 | <th valign="top">Qt data type | 
|---|
| 426 | <th valign="top">COM property | 
|---|
| 427 | <tr bgcolor="#f0f0f0"> | 
|---|
| 428 | <td valign="top">bool | 
|---|
| 429 | <td valign="top">VARIANT_BOOL | 
|---|
| 430 | <tr bgcolor="#d0d0d0"> | 
|---|
| 431 | <td valign="top">QString | 
|---|
| 432 | <td valign="top">BSTR | 
|---|
| 433 | <tr bgcolor="#f0f0f0"> | 
|---|
| 434 | <td valign="top">QCString | 
|---|
| 435 | <td valign="top">BSTR | 
|---|
| 436 | <tr bgcolor="#d0d0d0"> | 
|---|
| 437 | <td valign="top">int | 
|---|
| 438 | <td valign="top">int | 
|---|
| 439 | <tr bgcolor="#f0f0f0"> | 
|---|
| 440 | <td valign="top">uint | 
|---|
| 441 | <td valign="top">unsigned int | 
|---|
| 442 | <tr bgcolor="#d0d0d0"> | 
|---|
| 443 | <td valign="top">double | 
|---|
| 444 | <td valign="top">double | 
|---|
| 445 | <tr bgcolor="#f0f0f0"> | 
|---|
| 446 | <td valign="top">Q_LLONG | 
|---|
| 447 | <td valign="top">CY | 
|---|
| 448 | <tr bgcolor="#d0d0d0"> | 
|---|
| 449 | <td valign="top">Q_ULLONG | 
|---|
| 450 | <td valign="top">CY | 
|---|
| 451 | <tr bgcolor="#f0f0f0"> | 
|---|
| 452 | <td valign="top">QColor | 
|---|
| 453 | <td valign="top">OLE_COLOR | 
|---|
| 454 | <tr bgcolor="#d0d0d0"> | 
|---|
| 455 | <td valign="top">QDate | 
|---|
| 456 | <td valign="top">DATE | 
|---|
| 457 | <tr bgcolor="#f0f0f0"> | 
|---|
| 458 | <td valign="top">QDateTime | 
|---|
| 459 | <td valign="top">DATE | 
|---|
| 460 | <tr bgcolor="#d0d0d0"> | 
|---|
| 461 | <td valign="top">QTime | 
|---|
| 462 | <td valign="top">DATE | 
|---|
| 463 | <tr bgcolor="#f0f0f0"> | 
|---|
| 464 | <td valign="top">QFont | 
|---|
| 465 | <td valign="top">IFontDisp* | 
|---|
| 466 | <tr bgcolor="#d0d0d0"> | 
|---|
| 467 | <td valign="top">QPixmap | 
|---|
| 468 | <td valign="top">IPictureDisp* | 
|---|
| 469 | <a href="#footnote2"><sup>(2)</sup></a><a name="footnote-call2"></a> | 
|---|
| 470 | <tr bgcolor="#f0f0f0"> | 
|---|
| 471 | <td valign="top">QVariant | 
|---|
| 472 | <td valign="top">VARIANT | 
|---|
| 473 | <tr bgcolor="#d0d0d0"> | 
|---|
| 474 | <td valign="top">QValueList<QVariant> | 
|---|
| 475 | <td valign="top">SAFEARRAY(VARIANT) | 
|---|
| 476 | <tr bgcolor="#f0f0f0"> | 
|---|
| 477 | <td valign="top">QStringList | 
|---|
| 478 | <td valign="top">SAFEARRAY(BSTR) | 
|---|
| 479 | <tr bgcolor="#d0d0d0"> | 
|---|
| 480 | <td valign="top">QByteArray | 
|---|
| 481 | <td valign="top">SAFEARRAY(BYTE) | 
|---|
| 482 | <tr bgcolor="#f0f0f0"> | 
|---|
| 483 | <td valign="top">QRect | 
|---|
| 484 | <td valign="top">User defined type | 
|---|
| 485 | <tr bgcolor="#d0d0d0"> | 
|---|
| 486 | <td valign="top">QSize | 
|---|
| 487 | <td valign="top">User defined type | 
|---|
| 488 | <tr bgcolor="#f0f0f0"> | 
|---|
| 489 | <td valign="top">QPoint | 
|---|
| 490 | <td valign="top">User defined type | 
|---|
| 491 | </table></center> | 
|---|
| 492 | <p> The Qt data types that are supported for parameters in signals and | 
|---|
| 493 | slots are: | 
|---|
| 494 | <center><table cellpadding="4" cellspacing="2" border="0"> | 
|---|
| 495 | <tr bgcolor="#a2c511"> | 
|---|
| 496 | <th valign="top">Qt data type | 
|---|
| 497 | <th valign="top">COM parameter | 
|---|
| 498 | <tr bgcolor="#d0d0d0"> | 
|---|
| 499 | <td valign="top">bool | 
|---|
| 500 | <td valign="top">[in] VARIANT_BOOL | 
|---|
| 501 | <tr bgcolor="#f0f0f0"> | 
|---|
| 502 | <td valign="top">bool& | 
|---|
| 503 | <td valign="top">[in, out] VARIANT_BOOL* | 
|---|
| 504 | <tr bgcolor="#d0d0d0"> | 
|---|
| 505 | <td valign="top">QString, const <a href="qstring.html">QString</a>& | 
|---|
| 506 | <td valign="top">[in] BSTR | 
|---|
| 507 | <tr bgcolor="#f0f0f0"> | 
|---|
| 508 | <td valign="top">QString& | 
|---|
| 509 | <td valign="top">[in, out] BSTR* | 
|---|
| 510 | <tr bgcolor="#d0d0d0"> | 
|---|
| 511 | <td valign="top">QCString, const <a href="qcstring.html">QCString</a>& | 
|---|
| 512 | <td valign="top">[in] BSTR | 
|---|
| 513 | <tr bgcolor="#f0f0f0"> | 
|---|
| 514 | <td valign="top">QString& | 
|---|
| 515 | <td valign="top">[in, out] BSTR* | 
|---|
| 516 | <tr bgcolor="#d0d0d0"> | 
|---|
| 517 | <td valign="top">int | 
|---|
| 518 | <td valign="top">[in] int | 
|---|
| 519 | <tr bgcolor="#f0f0f0"> | 
|---|
| 520 | <td valign="top">int& | 
|---|
| 521 | <td valign="top">[in,out] int | 
|---|
| 522 | <tr bgcolor="#d0d0d0"> | 
|---|
| 523 | <td valign="top">uint | 
|---|
| 524 | <td valign="top">[in] unsigned int | 
|---|
| 525 | <tr bgcolor="#f0f0f0"> | 
|---|
| 526 | <td valign="top">uint& | 
|---|
| 527 | <td valign="top">[in, out] unsigned int* | 
|---|
| 528 | <tr bgcolor="#d0d0d0"> | 
|---|
| 529 | <td valign="top">double | 
|---|
| 530 | <td valign="top">[in] double | 
|---|
| 531 | <tr bgcolor="#f0f0f0"> | 
|---|
| 532 | <td valign="top">double& | 
|---|
| 533 | <td valign="top">[in, out] double* | 
|---|
| 534 | <tr bgcolor="#d0d0d0"> | 
|---|
| 535 | <td valign="top">QColor, const <a href="qcolor.html">QColor</a>& | 
|---|
| 536 | <td valign="top">[in] OLE_COLOR | 
|---|
| 537 | <tr bgcolor="#f0f0f0"> | 
|---|
| 538 | <td valign="top">QColor& | 
|---|
| 539 | <td valign="top">[in, out] OLE_COLOR* | 
|---|
| 540 | <tr bgcolor="#d0d0d0"> | 
|---|
| 541 | <td valign="top">QDate, const <a href="qdate.html">QDate</a>& | 
|---|
| 542 | <td valign="top">[in] DATE | 
|---|
| 543 | <tr bgcolor="#f0f0f0"> | 
|---|
| 544 | <td valign="top">QDate& | 
|---|
| 545 | <td valign="top">[in, out] DATE* | 
|---|
| 546 | <tr bgcolor="#d0d0d0"> | 
|---|
| 547 | <td valign="top">QDateTime, const <a href="qdatetime.html">QDateTime</a>& | 
|---|
| 548 | <td valign="top">[in] DATE | 
|---|
| 549 | <tr bgcolor="#f0f0f0"> | 
|---|
| 550 | <td valign="top">QDateTime& | 
|---|
| 551 | <td valign="top">[in, out] DATE* | 
|---|
| 552 | <tr bgcolor="#d0d0d0"> | 
|---|
| 553 | <td valign="top">QFont, const <a href="qfont.html">QFont</a>& | 
|---|
| 554 | <td valign="top">[in] IFontDisp* | 
|---|
| 555 | <tr bgcolor="#f0f0f0"> | 
|---|
| 556 | <td valign="top">QFont& | 
|---|
| 557 | <td valign="top">[in, out] IFontDisp** | 
|---|
| 558 | <tr bgcolor="#d0d0d0"> | 
|---|
| 559 | <td valign="top">QPixmap, const <a href="qpixmap.html">QPixmap</a>& | 
|---|
| 560 | <td valign="top">[in] IPictureDisp* | 
|---|
| 561 | <tr bgcolor="#f0f0f0"> | 
|---|
| 562 | <td valign="top">QPixmap& | 
|---|
| 563 | <td valign="top">[in, out] IPictureDisp** | 
|---|
| 564 | <tr bgcolor="#d0d0d0"> | 
|---|
| 565 | <td valign="top">QValueList<QVariant>, const <a href="qvaluelist.html">QValueList</a><QVariant>& | 
|---|
| 566 | <td valign="top">[in] SAFEARRAY(VARIANT) | 
|---|
| 567 | <tr bgcolor="#f0f0f0"> | 
|---|
| 568 | <td valign="top">QValueList<QVariant>& | 
|---|
| 569 | <td valign="top">[in, out] SAFEARRAY(VARIANT)* | 
|---|
| 570 | <tr bgcolor="#d0d0d0"> | 
|---|
| 571 | <td valign="top">QStringList, const <a href="qstringlist.html">QStringList</a>& | 
|---|
| 572 | <td valign="top">[in] SAFEARRAY(BSTR) | 
|---|
| 573 | <tr bgcolor="#f0f0f0"> | 
|---|
| 574 | <td valign="top">QStringList& | 
|---|
| 575 | <td valign="top">[in, out] SAFEARRAY(BSTR)* | 
|---|
| 576 | <tr bgcolor="#d0d0d0"> | 
|---|
| 577 | <td valign="top">QByteArray, const <a href="qbytearray.html">QByteArray</a>& | 
|---|
| 578 | <td valign="top">[in] SAFEARRAY(BYTE) | 
|---|
| 579 | <tr bgcolor="#f0f0f0"> | 
|---|
| 580 | <td valign="top">QByteArray& | 
|---|
| 581 | <td valign="top">[in, out] SAFEARRAY(BYTE)* | 
|---|
| 582 | <tr bgcolor="#d0d0d0"> | 
|---|
| 583 | <td valign="top">QObject* | 
|---|
| 584 | <td valign="top">[in] IDispatch* | 
|---|
| 585 | <tr bgcolor="#f0f0f0"> | 
|---|
| 586 | <td valign="top">QRect& | 
|---|
| 587 | <a href="#footnote3"><sup>(3)</sup></a><a name="footnote-call3"></a> | 
|---|
| 588 | <td valign="top">[in, out] struct <a href="qrect.html">QRect</a> (user defined) | 
|---|
| 589 | <tr bgcolor="#d0d0d0"> | 
|---|
| 590 | <td valign="top">QSize& | 
|---|
| 591 | <td valign="top">[in, out] struct <a href="qsize.html">QSize</a> (user defined) | 
|---|
| 592 | <tr bgcolor="#f0f0f0"> | 
|---|
| 593 | <td valign="top">QPoint& | 
|---|
| 594 | <td valign="top">[in, out] struct <a href="qpoint.html">QPoint</a> (user defined) | 
|---|
| 595 | </table></center> | 
|---|
| 596 | <p> Also supported are exported enums and sets (see Q_ENUMS and Q_SETS). | 
|---|
| 597 | The in-parameter types are also supported as return values. | 
|---|
| 598 | <p> Properties and signals/slots that have parameters using any other | 
|---|
| 599 | data types are ignored by the QActiveX framework. | 
|---|
| 600 | <p> <h3> Sub-Objects | 
|---|
| 601 | </h3> | 
|---|
| 602 | <a name="5-2"></a><p> COM objects can have multiple sub-objects that can represent a sub element | 
|---|
| 603 | of the COM object. A COM object representing a multi-document spread sheet | 
|---|
| 604 | application can for example provide one sub-object for each spread sheet. | 
|---|
| 605 | <p> Any <a href="qobject.html">QObject</a> subclass can be used as the type for a sub object in ActiveX. The | 
|---|
| 606 | <a href="qaxfactory.html">QAxFactory</a> implementation (see below) needs to return the classname of the | 
|---|
| 607 | sub type as one key in the featureList() implementation, as well as the IDs | 
|---|
| 608 | for the COM class, the interface and event interface of that type. Then the | 
|---|
| 609 | type can be used as e.g. the return value or paramter of a slot. | 
|---|
| 610 | <p> <h3> Property Notification | 
|---|
| 611 | </h3> | 
|---|
| 612 | <a name="5-3"></a><p> To make the properties bindable for the ActiveX client, use multiple | 
|---|
| 613 | inheritance from the <a href="qaxbindable.html">QAxBindable</a> class: | 
|---|
| 614 | <p> | 
|---|
| 615 | <pre> | 
|---|
| 616 | #include <qwidget.h> | 
|---|
| 617 | <b>#include <qaxbindable.h></b> | 
|---|
| 618 |  | 
|---|
| 619 | class MyActiveX : public <a href="qwidget.html">QWidget</a><b>, public QAxBindable</b> | 
|---|
| 620 | { | 
|---|
| 621 | Q_OBJECT | 
|---|
| 622 | </pre> | 
|---|
| 623 |  | 
|---|
| 624 | When implementing the property write functions, use the | 
|---|
| 625 | QAxBindable class's requestPropertyChange() and propertyChanged() | 
|---|
| 626 | functions to allow ActiveX clients to bind to the control | 
|---|
| 627 | properties. | 
|---|
| 628 | <a href="#footnote4"><sup>(4)</sup></a><a name="footnote-call4"></a> | 
|---|
| 629 | <p> <h2> Serving Controls | 
|---|
| 630 | </h2> | 
|---|
| 631 | <a name="6"></a><p> To make an ActiveX control available to the COM system it must | 
|---|
| 632 | be registered in the system registry using five unique | 
|---|
| 633 | identifiers. These identifiers are provided by tools like <tt>guidgen</tt> or <tt>uuidgen</tt>. The registration information allows COM to | 
|---|
| 634 | localize the binary providing a requested ActiveX control, | 
|---|
| 635 | marshall remote procedure calls to the control and read type | 
|---|
| 636 | information about the methods and properties exposed by the | 
|---|
| 637 | control. | 
|---|
| 638 | <p> To create the ActiveX control when the client asks for it the | 
|---|
| 639 | server must export an implementation of a <a href="qaxfactory.html">QAxFactory</a>. Use the | 
|---|
| 640 | default factory when the server provides only a single ActiveX | 
|---|
| 641 | control, and implement a subclass of QAxFactory to provide | 
|---|
| 642 | multiple ActiveX controls. The default factory is available | 
|---|
| 643 | through a macro that takes the identifiers COM requires to locate | 
|---|
| 644 | the ActiveX control on the target system: | 
|---|
| 645 | <p> <pre> | 
|---|
| 646 | QAXFACTORY_DEFAULT ( MyActiveX, | 
|---|
| 647 | "{ad90301a-849e-4e8b-9a91-0a6dc5f6461f}", | 
|---|
| 648 | "{87a5b65e-7fa9-4dc6-a176-47295988dcbd}", | 
|---|
| 649 | "{a6130ae9-8327-47ec-815b-d0b45a0d6e5e}", | 
|---|
| 650 | "{26c4e136-4e23-4347-af37-faf933b027e9}", | 
|---|
| 651 | "{a8f21901-7ff7-4f6a-b939-789620c03d83}" ) | 
|---|
| 652 | </pre> | 
|---|
| 653 |  | 
|---|
| 654 | <p> The <a href="qaxfactory.html">QAxFactory class documentation</a> explains | 
|---|
| 655 | how to use this macro, and how to implement and use custom factories. | 
|---|
| 656 | <p> For out-of-process executable servers you can implement a main() | 
|---|
| 657 | function to instantiate a <a href="qapplication.html">QApplication</a> object and enter the event | 
|---|
| 658 | loop just like any normal Qt application. By default the | 
|---|
| 659 | application will start as a standard Qt application, but if you | 
|---|
| 660 | pass <tt>-activex</tt> on the command line it will start as an ActiveX | 
|---|
| 661 | server. Use <a href="qaxfactory.html#isServer">QAxFactory::isServer</a>() to create and run a standard | 
|---|
| 662 | application interface, or to prevent a stand-alone execution: | 
|---|
| 663 | <p> | 
|---|
| 664 | <pre> | 
|---|
| 665 | #include <qapplication.h> | 
|---|
| 666 | <b>#include <qaxfactory.h></b> | 
|---|
| 667 |  | 
|---|
| 668 | int main( int argc, char **argv ) | 
|---|
| 669 | { | 
|---|
| 670 | QApplication app( argc, argv ); | 
|---|
| 671 | <b>if ( !QAxFactory::isServer() ) { | 
|---|
| 672 | // create and show main window... | 
|---|
| 673 | }</b> | 
|---|
| 674 | return app.exec(); | 
|---|
| 675 | } | 
|---|
| 676 | </pre> | 
|---|
| 677 |  | 
|---|
| 678 | This is however not necessary as ActiveQt provides a default implementation | 
|---|
| 679 | of a main function. The default implemenation calls <a href="qaxfactory.html#startServer">QAxFactory::startServer</a>(), | 
|---|
| 680 | creates a QApplication instance and calls exec(). | 
|---|
| 681 | <p> To build the ActiveX server executable run <a href="qmake-manual.html">qmake</a> to generate the makefile, and use your compiler's | 
|---|
| 682 | make tool as for any other Qt application. The make process will | 
|---|
| 683 | also register the controls in the system registry by calling the | 
|---|
| 684 | resulting executable with the <tt>-regserver</tt> command line option. | 
|---|
| 685 | <p> If the ActiveX server is an executable, the following command line | 
|---|
| 686 | options are supported: | 
|---|
| 687 | <center><table cellpadding="4" cellspacing="2" border="0"> | 
|---|
| 688 | <tr bgcolor="#a2c511"> <th valign="top">Option <th valign="top">Result | 
|---|
| 689 | <tr bgcolor="#d0d0d0"> <td valign="top"><tt>-regserver</tt> <td valign="top">Registers the server in the system registry | 
|---|
| 690 | <tr bgcolor="#f0f0f0"> <td valign="top"><tt>-unregserver</tt> <td valign="top">Unregisters the server from the system registry | 
|---|
| 691 | <tr bgcolor="#d0d0d0"> <td valign="top"><tt>-activex</tt> <td valign="top">Starts the application as an ActiveX server | 
|---|
| 692 | <tr bgcolor="#f0f0f0"> <td valign="top"><tt>-dumpidl <file> -version x.y</tt> <td valign="top">Writes the server's IDL to the | 
|---|
| 693 | specified file. The type library will have version x.y | 
|---|
| 694 | </table></center> | 
|---|
| 695 | <p> In-process servers can be registered using the <tt>regsvr32</tt> tool available | 
|---|
| 696 | on all Windows systems. | 
|---|
| 697 | <p> <h3> Distributing QAxServer binaries | 
|---|
| 698 | </h3> | 
|---|
| 699 | <a name="6-1"></a><p> ActiveX servers written with Qt can use Qt either as a shared | 
|---|
| 700 | library, or have Qt linked statically into the binary. Both ways | 
|---|
| 701 | will produce rather large packages (either the server binary | 
|---|
| 702 | itself becomes large, or you have to ship the Qt DLL). | 
|---|
| 703 | <p> <h4> Installing stand-alone Servers | 
|---|
| 704 | </h4> | 
|---|
| 705 | <a name="6-1-1"></a><p> When your ActiveX server can also run as a stand-alone application, | 
|---|
| 706 | run the server executable with the <tt>-regserver</tt> command line | 
|---|
| 707 | parameter after installing the executable on the target system. | 
|---|
| 708 | After that the controls provided by the server will be available to | 
|---|
| 709 | ActiveX clients. | 
|---|
| 710 | <p> <h4> Installing In-process Servers | 
|---|
| 711 | </h4> | 
|---|
| 712 | <a name="6-1-2"></a><p> When your ActiveX server is part of an installation package, use the | 
|---|
| 713 | <tt>regsvr32</tt> tool provided by Microsoft to register the controls on | 
|---|
| 714 | the target system. If this tool is not present, load the DLL into | 
|---|
| 715 | your installer process, resolve the <tt>DllRegisterServer</tt> symbol and | 
|---|
| 716 | call the function: | 
|---|
| 717 | <p> <pre> | 
|---|
| 718 | HMODULE dll = LoadLibrary( "myserver.dll" ); | 
|---|
| 719 | typedef HRESULT(__stdcall *DllRegisterServerProc)(); | 
|---|
| 720 | DllRegisterServerProc DllRegisterServer = | 
|---|
| 721 | (DllRegisterServerProc)GetProcAddress( dll, "DllRegisterServer" ); | 
|---|
| 722 |  | 
|---|
| 723 | HRESULT res = E_FAIL; | 
|---|
| 724 | if ( DllRegisterServer ) | 
|---|
| 725 | res = DllRegisterServer(); | 
|---|
| 726 | if ( res != S_OK ) | 
|---|
| 727 | // error handling | 
|---|
| 728 | </pre> | 
|---|
| 729 |  | 
|---|
| 730 | <p> <h4> Distributing Servers over the Internet | 
|---|
| 731 | </h4> | 
|---|
| 732 | <a name="6-1-3"></a><p> If you want to use controls in your server in web-pages you need to | 
|---|
| 733 | make the server available to the browser used to view your page, and | 
|---|
| 734 | you need to specify the location of the server package in your page. | 
|---|
| 735 | <p> To specify the location of a server, use the CODEBASE attribute in | 
|---|
| 736 | the OBJECT tag of your web-site. The value can point to the server | 
|---|
| 737 | file itself, to an <tt>INF</tt> file listing other files the server requires | 
|---|
| 738 | (e.g. the Qt DLL), or a compressed <tt>CAB</tt> archive. | 
|---|
| 739 | <p> INF and CAB files are documented in almost every book available about | 
|---|
| 740 | ActiveX and COM programming as well as in the MSDN library and various | 
|---|
| 741 | other Online resources. The examples include INF files that can be used | 
|---|
| 742 | to build CAB archives: | 
|---|
| 743 | <p> | 
|---|
| 744 |  | 
|---|
| 745 | <pre>    [version] | 
|---|
| 746 | signature="$CHICAGO$" | 
|---|
| 747 | AdvancedINF=2.0 | 
|---|
| 748 | [Add.Code] | 
|---|
| 749 | simpleax.exe=simpleax.exe | 
|---|
| 750 | [simpleax.exe] | 
|---|
| 751 | file-win32-x86=thiscab | 
|---|
| 752 | clsid={DF16845C-92CD-4AAB-A982-EB9840E74669} | 
|---|
| 753 | RegisterServer=yes | 
|---|
| 754 | </pre> | 
|---|
| 755 | <p> The CABARC tool from Microsoft can easily generate CAB archives: | 
|---|
| 756 | <pre> cabarc N simpleax.cab simpleax.exe simple.inf </pre> | 
|---|
| 757 |  | 
|---|
| 758 | <p> The INF files assume a static build of Qt, so no dependencies to other DLLs | 
|---|
| 759 | are listed in the INF files. To distribute an ActiveX server depending on | 
|---|
| 760 | DLLs you must add the dependencies, and provide the library files | 
|---|
| 761 | with the archive. | 
|---|
| 762 | <p> <h2> Using the Controls | 
|---|
| 763 | </h2> | 
|---|
| 764 | <a name="7"></a><p> To use the ActiveX controls, e.g. to embed them in a web page, use | 
|---|
| 765 | the <tt><object></tt> HTML tag. | 
|---|
| 766 | <p> <pre> | 
|---|
| 767 | <object ID="MyActiveX1" CLASSID="CLSID:ad90301a-849e-4e8b-9a91-0a6dc5f6461f"> | 
|---|
| 768 | ... | 
|---|
| 769 | <\object> | 
|---|
| 770 | </pre> | 
|---|
| 771 |  | 
|---|
| 772 | <p> To initialize the control's properties, use | 
|---|
| 773 | <pre> | 
|---|
| 774 | <object ID=...> | 
|---|
| 775 | <param name="name" value="value"> | 
|---|
| 776 | <\object> | 
|---|
| 777 | </pre> | 
|---|
| 778 |  | 
|---|
| 779 | <p> If the web browser supports scripting use JavaScript, VBScript and | 
|---|
| 780 | forms to script the control. The <a href="qaxserver-examples.html">examples</a> include demonstration HTML pages for the | 
|---|
| 781 | example controls. | 
|---|
| 782 | <p> <h3> Supported and Unsupported ActiveX clients | 
|---|
| 783 | </h3> | 
|---|
| 784 | <a name="7-1"></a><p> The following is largly based on our own experiements with ActiveX | 
|---|
| 785 | controls and client applications, and is by no means complete. | 
|---|
| 786 | <p> <h4> Supported Clients | 
|---|
| 787 | </h4> | 
|---|
| 788 | <a name="7-1-1"></a><p> These standard applications work with ActiveX controls developed with | 
|---|
| 789 | ActiveQt. Note that some clients support only in-process controls. | 
|---|
| 790 | <p> <ul> | 
|---|
| 791 | <li> Internet Explorer | 
|---|
| 792 | <li> Microsoft ActiveX Control Test Container | 
|---|
| 793 | <li> Microsoft Visual Studio 6.0 | 
|---|
| 794 | <li> Microsoft Visual Studio.NET/2003 | 
|---|
| 795 | <li> Microsoft Visual Basic 6.0 | 
|---|
| 796 | <li> MFC- and ATL-based containers | 
|---|
| 797 | <li> Sybase PowerBuilder | 
|---|
| 798 | <li> ActiveQt based containers | 
|---|
| 799 | </ul> | 
|---|
| 800 | <p> Microsoft Office applications are supported, but you need to register | 
|---|
| 801 | the controls as "Insertable" objects. Reimplement <tt>QAxFactory::registerClass</tt> | 
|---|
| 802 | to add this attribute to the COM class, or set the "Insertable" class info | 
|---|
| 803 | for your class to "yes" using the Q_CLASSINFO macro. | 
|---|
| 804 | <p> <h4> Unsupported Clients | 
|---|
| 805 | </h4> | 
|---|
| 806 | <a name="7-1-2"></a><p> We have not managed to make ActiveQt based COM objects work with the | 
|---|
| 807 | following client applications. | 
|---|
| 808 | <p> <ul> | 
|---|
| 809 | <li> Borland C++ Builder (Versions 5 and 6) | 
|---|
| 810 | <li> Borland Delphi | 
|---|
| 811 | </ul> | 
|---|
| 812 | <p> <h2> Enhanced features | 
|---|
| 813 | </h2> | 
|---|
| 814 | <a name="8"></a><p> <h3> Fewer methods and properties | 
|---|
| 815 | </h3> | 
|---|
| 816 | <a name="8-1"></a><p> By default all ActiveX controls expose not only their own methods | 
|---|
| 817 | and properties to ActiveX clients, but also those of all super | 
|---|
| 818 | classes, including <a href="qwidget.html">QWidget</a>. | 
|---|
| 819 | <p> This can be controlled by reimplementing <a href="qaxfactory.html">QAxFactory</a>'s | 
|---|
| 820 | exposeToSuperClass() function. Reimplement the function to return | 
|---|
| 821 | the last (furthest up the inheritance hierarchy) super class that | 
|---|
| 822 | should be exposed: | 
|---|
| 823 | <p> <pre> | 
|---|
| 824 | QString MyFactory::exposeToSuperClass( const <a href="qstring.html">QString</a> &key ) const | 
|---|
| 825 | { | 
|---|
| 826 | if ( key == "SmallActiveX" ) | 
|---|
| 827 | return key; | 
|---|
| 828 | return QAxFactory::exposeToSuperClass( key ); | 
|---|
| 829 | } | 
|---|
| 830 | </pre> | 
|---|
| 831 |  | 
|---|
| 832 | <p> The SmallActiveX control will only expose its own functions and | 
|---|
| 833 | properties to clients, while all other ActiveX controls provided | 
|---|
| 834 | by this factory will expose their own functions and properties and | 
|---|
| 835 | also those of all their super classes including QWidget. The | 
|---|
| 836 | SmallActiveX class can of course propagate some of the QWidget | 
|---|
| 837 | functions and properties into its own interface. | 
|---|
| 838 | <p> <h3> Class Information and Tuning | 
|---|
| 839 | </h3> | 
|---|
| 840 | <a name="8-2"></a><p> An alternative way to reimplementing QAxFactory to have more control | 
|---|
| 841 | about how objects are registered or exposed is to provide class | 
|---|
| 842 | specific information using the Q_CLASSINFO macro, which is part of | 
|---|
| 843 | Qt's meta object system. | 
|---|
| 844 | <p> <center><table cellpadding="4" cellspacing="2" border="0"> | 
|---|
| 845 | <tr bgcolor="#a2c511"> | 
|---|
| 846 | <th valign="top">Key | 
|---|
| 847 | <th valign="top">Meaning of value | 
|---|
| 848 | <tr bgcolor="#d0d0d0"> | 
|---|
| 849 | <td valign="top">Version | 
|---|
| 850 | <td valign="top">The version of the class (1.0 is default) | 
|---|
| 851 | <tr bgcolor="#f0f0f0"> | 
|---|
| 852 | <td valign="top">Description | 
|---|
| 853 | <td valign="top">A string describing the class. | 
|---|
| 854 | <tr bgcolor="#d0d0d0"> | 
|---|
| 855 | <td valign="top">ClassID | 
|---|
| 856 | <td valign="top">The class ID. | 
|---|
| 857 | You must reimplement QAxFactory::classID if not specified. | 
|---|
| 858 | <tr bgcolor="#f0f0f0"> | 
|---|
| 859 | <td valign="top">InterfaceID | 
|---|
| 860 | <td valign="top">The interface ID. | 
|---|
| 861 | You must reimplement QAxFactory::interfaceID if not specified. | 
|---|
| 862 | <tr bgcolor="#d0d0d0"> | 
|---|
| 863 | <td valign="top">EventsID | 
|---|
| 864 | <td valign="top">The event interface ID. | 
|---|
| 865 | No signals are exposed as COM events if not specified. | 
|---|
| 866 | <tr bgcolor="#f0f0f0"> | 
|---|
| 867 | <td valign="top">DefaultProperty | 
|---|
| 868 | <td valign="top">The property specified represents the default property of this class. | 
|---|
| 869 | Ie. the default property of a push button would be "text". | 
|---|
| 870 | <tr bgcolor="#d0d0d0"> | 
|---|
| 871 | <td valign="top">DefaultSignal | 
|---|
| 872 | <td valign="top">The signal specified respresents the default signal of this class. | 
|---|
| 873 | Ie. the default signal of a push button would be "clicked". | 
|---|
| 874 | <tr bgcolor="#f0f0f0"> | 
|---|
| 875 | <td valign="top">LicenseKey | 
|---|
| 876 | <td valign="top">Object creation requires the specified license key. The key can be | 
|---|
| 877 | empty to require a licensed machine. By default classes are not | 
|---|
| 878 | licensed. Also see the following section. | 
|---|
| 879 | <tr bgcolor="#d0d0d0"> | 
|---|
| 880 | <td valign="top">StockEvents | 
|---|
| 881 | <td valign="top">Objects expose stock events if value is "yes". | 
|---|
| 882 | See <a href="qaxfactory.html#hasStockEvents">QAxFactory::hasStockEvents</a>() | 
|---|
| 883 | <tr bgcolor="#f0f0f0"> | 
|---|
| 884 | <td valign="top">ToSuperClass | 
|---|
| 885 | <td valign="top">Objects expose functionality of all super classes up to and | 
|---|
| 886 | including the class name in value. | 
|---|
| 887 | See <a href="qaxfactory.html#exposeToSuperClass">QAxFactory::exposeToSuperClass</a>() | 
|---|
| 888 | <tr bgcolor="#d0d0d0"> | 
|---|
| 889 | <td valign="top">Insertable | 
|---|
| 890 | <td valign="top">If the value is "yes" the class is registered to be "Insertable" | 
|---|
| 891 | and will be listed in OLE 2 containers (ie. Microsoft Office). This | 
|---|
| 892 | attribute is not be set by default. | 
|---|
| 893 | <tr bgcolor="#f0f0f0"> | 
|---|
| 894 | <td valign="top">Aggregatable | 
|---|
| 895 | <td valign="top">If the value is "no" the class does not support aggregation. By | 
|---|
| 896 | default aggregation is supported. | 
|---|
| 897 | <tr bgcolor="#d0d0d0"> | 
|---|
| 898 | <td valign="top">Creatable | 
|---|
| 899 | <td valign="top">If the value is "no" the class cannot be created by the client, | 
|---|
| 900 | and is only available through the API of another class (ie. the | 
|---|
| 901 | class is a sub-type). | 
|---|
| 902 | <tr bgcolor="#f0f0f0"> | 
|---|
| 903 | <td valign="top">RegisterObject | 
|---|
| 904 | <td valign="top">If the value is "yes" objects of this class are registered with | 
|---|
| 905 | OLE and accessible from the running object table (ie. clients | 
|---|
| 906 | can connect to an already running instance of this class). This | 
|---|
| 907 | attribute is only supported in out-of-process servers. | 
|---|
| 908 | </table></center> | 
|---|
| 909 | <p> Note that both keys and values are case sensitive. | 
|---|
| 910 | <p> The following declares version 2.0 of a class that exposes only its | 
|---|
| 911 | own API, and is available in the "Insert Objects" dialog of Microsoft | 
|---|
| 912 | Office applications. | 
|---|
| 913 | <p> | 
|---|
| 914 | <pre> | 
|---|
| 915 | class MyActiveX : public <a href="qwidget.html">QWidget</a> | 
|---|
| 916 | { | 
|---|
| 917 | Q_OBJECT | 
|---|
| 918 | <b>Q_CLASSINFO("Version", "2.0") | 
|---|
| 919 | Q_CLASSINFO("ClassID", "{7a4cffd8-cbcd-4ae9-ae7e-343e1e5710df}") | 
|---|
| 920 | Q_CLASSINFO("InterfaceID", "{6fb035bf-8019-48d8-be51-ef05427d8994}") | 
|---|
| 921 | Q_CLASSINFO("EventsID", "{c42fffdf-6557-47c9-817a-2da2228bc29c}") | 
|---|
| 922 | Q_CLASSINFO("Insertable", "yes") | 
|---|
| 923 | Q_CLASSINFO("ToSuperClass", "MyActiveX")</b> | 
|---|
| 924 |  | 
|---|
| 925 | Q_PROPERTY( ... | 
|---|
| 926 | public: | 
|---|
| 927 | MyActiveX(QWidget *parent = 0, const char *name = 0); | 
|---|
| 928 |  | 
|---|
| 929 | ... | 
|---|
| 930 | }; | 
|---|
| 931 | </pre> | 
|---|
| 932 |  | 
|---|
| 933 | <h3> Developing licensed components | 
|---|
| 934 | </h3> | 
|---|
| 935 | <a name="8-3"></a><p> If you develop components you might want to control who is able to instantiate | 
|---|
| 936 | those components. Since the server binary can be shipped to and registered on | 
|---|
| 937 | any client machine it is possible for anybody to use those components in his | 
|---|
| 938 | own software. | 
|---|
| 939 | <p> Licensing components can be done using a variety of techniques, e.g. the code | 
|---|
| 940 | creating the control can provide a license key, or the machine on which the | 
|---|
| 941 | control is supposed to run needs to be licensed. | 
|---|
| 942 | <p> To mark a Qt class as licensed specify a "LicenseKey" using the <tt>Q_CLASSINFO</tt> | 
|---|
| 943 | macro. | 
|---|
| 944 |  | 
|---|
| 945 | <pre> | 
|---|
| 946 | class MyLicensedControl : public <a href="qwidget.html">QWidget</a> | 
|---|
| 947 | { | 
|---|
| 948 | Q_OBJECT | 
|---|
| 949 | <b>Q_CLASSINFO("LicenseKey", "<key string>")</b> | 
|---|
| 950 | ... | 
|---|
| 951 | }; | 
|---|
| 952 | </pre> | 
|---|
| 953 |  | 
|---|
| 954 | The key is required to be able to create an instance of <tt>MyLicensedControl</tt> | 
|---|
| 955 | on a machine that is not licensed itself. The licensed developer can now | 
|---|
| 956 | redistributes the server binary with his application, which creates the control | 
|---|
| 957 | using the value of "LicenseKey", while users of the application cannot create | 
|---|
| 958 | the control without the license key. | 
|---|
| 959 | <p> If a single license key for the control is not sufficient (ie. you want | 
|---|
| 960 | differnet developers to receive different license keys) you can specify an | 
|---|
| 961 | empty key to indicate that the control requires a license, and reimplement | 
|---|
| 962 | <a href="qaxfactory.html#validateLicenseKey">QAxFactory::validateLicenseKey</a>() to verify that a license exists on the | 
|---|
| 963 | system (ie. through a license file). | 
|---|
| 964 | <p> <h3> More Interfaces | 
|---|
| 965 | </h3> | 
|---|
| 966 | <a name="8-4"></a><p> ActiveX controls provided by ActiveQt servers support a minimal set of COM | 
|---|
| 967 | interfaces to implement the OLE specifications. When the ActiveX class inherits | 
|---|
| 968 | from the <a href="qaxbindable.html">QAxBindable</a> class it can also implement additional COM interfaces. | 
|---|
| 969 | <p> Create a new subclass of <a href="qaxaggregated.html">QAxAggregated</a> and use multiple inheritance | 
|---|
| 970 | to subclass additional COM interface classes. | 
|---|
| 971 | <p> <pre> | 
|---|
| 972 | class AxImpl : public <a href="qaxaggregated.html">QAxAggregated</a>, public ISomeCOMInterface | 
|---|
| 973 | { | 
|---|
| 974 | public: | 
|---|
| 975 | AxImpl() {} | 
|---|
| 976 |  | 
|---|
| 977 | long queryInterface( const <a href="quuid.html">QUuid</a> &iid, void **iface ); | 
|---|
| 978 |  | 
|---|
| 979 | // IUnknown | 
|---|
| 980 | QAXAGG_IUNKNOWN | 
|---|
| 981 |  | 
|---|
| 982 | // ISomeCOMInterface | 
|---|
| 983 | ... | 
|---|
| 984 | } | 
|---|
| 985 | </pre> | 
|---|
| 986 |  | 
|---|
| 987 | <p> Reimplement the <tt>queryInterface()</tt> function to support the additional | 
|---|
| 988 | COM interfaces. | 
|---|
| 989 | <p> <pre> | 
|---|
| 990 | long AxImpl::queryInterface( const <a href="quuid.html">QUuid</a> &iid, void **iface ) | 
|---|
| 991 | { | 
|---|
| 992 | *iface = 0; | 
|---|
| 993 | if ( iid == IID_ISomeCOMInterface ) | 
|---|
| 994 | *iface = (ISomeCOMInterface*)this; | 
|---|
| 995 | else | 
|---|
| 996 | return E_NOINTERFACE; | 
|---|
| 997 |  | 
|---|
| 998 | AddRef(); | 
|---|
| 999 | return S_OK; | 
|---|
| 1000 | } | 
|---|
| 1001 | </pre> | 
|---|
| 1002 |  | 
|---|
| 1003 | <p> Since <tt>ISomeCOMInterface</tt> is a subclass of <tt>IUnknown</tt> you will have | 
|---|
| 1004 | to implement the <tt>QueryInterface</tt>, <tt>AddRef</tt> and <tt>Release</tt> functions. | 
|---|
| 1005 | Use the <tt>QAXAGG_IUNKNOWN</tt> macro in your class definition to do that. If | 
|---|
| 1006 | you implement the IUnknown functions manually, delegate the calls to the | 
|---|
| 1007 | interface pointer returned by the controllingUnknown() function, e.g. | 
|---|
| 1008 | <pre> | 
|---|
| 1009 | HRESULT AxImpl::QueryInterface( REFIID iid, void **iface ) | 
|---|
| 1010 | { | 
|---|
| 1011 | return controllingUnknown()->QueryInterface( iid, iface ); | 
|---|
| 1012 | } | 
|---|
| 1013 | </pre> | 
|---|
| 1014 |  | 
|---|
| 1015 | Do not support the <tt>IUnknown</tt> interface itself in your <tt>queryInterface()</tt> | 
|---|
| 1016 | implementation. | 
|---|
| 1017 | <p> Implement the methods of the COM interfaces, and use QAxAggregated::Object() | 
|---|
| 1018 | if you need to make calls to the <a href="qobject.html">QObject</a> subclass implementing the control. | 
|---|
| 1019 | <p> In your <a href="qaxbindable.html">QAxBindable</a> subclass, implement <tt>createAggregate()</tt> to return | 
|---|
| 1020 | a new object of the <a href="qaxaggregated.html">QAxAggregated</a> subclass. | 
|---|
| 1021 | <p> | 
|---|
| 1022 | <pre> | 
|---|
| 1023 | class MyActiveX : public <a href="qwidget.html">QWidget</a>, | 
|---|
| 1024 | <b>public QAxBindable</b> | 
|---|
| 1025 | { | 
|---|
| 1026 | Q_OBJECT | 
|---|
| 1027 | public: | 
|---|
| 1028 | MyActiveX( QWidget *parent, const char *name = 0 ); | 
|---|
| 1029 |  | 
|---|
| 1030 | <b>QAxAggregated *createAggregate() | 
|---|
| 1031 | { | 
|---|
| 1032 | return new AxImpl(); | 
|---|
| 1033 | } | 
|---|
| 1034 | </b> | 
|---|
| 1035 | }; | 
|---|
| 1036 | </pre> | 
|---|
| 1037 |  | 
|---|
| 1038 | <hr> | 
|---|
| 1039 | <ol> <li><a name="footnote1"></a> | 
|---|
| 1040 |  | 
|---|
| 1041 | If a standard constructor is not present the compiler will issue | 
|---|
| 1042 | an error "no overloaded function takes 2 parameters" when using | 
|---|
| 1043 | the default factory through the <a href="qaxfactory.html#QAXFACTORY_DEFAULT">QAXFACTORY_DEFAULT</a> macro. If you | 
|---|
| 1044 | cannot provide a standard constructor you must implement a <a href="qaxfactory.html">QAxFactory</a> custom factory and call the constructor you have in | 
|---|
| 1045 | your implementation of QAxFactory::create. | 
|---|
| 1046 | <a href="#footnote-call1">Back...</a> <li><a name="footnote2"></a> | 
|---|
| 1047 |  | 
|---|
| 1048 | COM cannot marshal IPictureDisp accross process boundaries, | 
|---|
| 1049 | so <a href="qpixmap.html">QPixmap</a> properties cannot be called for out-of-process servers. You | 
|---|
| 1050 | can however marshal the image data via e.g. temporary files. See the | 
|---|
| 1051 | Microsoft | 
|---|
| 1052 | <a href="http://support.microsoft.com/default.aspx?scid=kb;[LN];Q150034">KB article | 
|---|
| 1053 | Q150034</a> for more information. | 
|---|
| 1054 | <a href="#footnote-call2">Back...</a> <li><a name="footnote3"></a> | 
|---|
| 1055 |  | 
|---|
| 1056 | OLE needs to marshal user defined types by reference (ByRef), and cannot | 
|---|
| 1057 | marshal them by value (ByVal). This is why const-references and object | 
|---|
| 1058 | 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 | 
|---|
| 1059 | servers with this datatype require Windows 98 or DCOM 1.2 to be installed. | 
|---|
| 1060 | <a href="#footnote-call3">Back...</a> <li><a name="footnote4"></a> | 
|---|
| 1061 |  | 
|---|
| 1062 | This is not required, but gives the client more control over | 
|---|
| 1063 | the ActiveX control. | 
|---|
| 1064 | <a href="#footnote-call4">Back...</a></ol> | 
|---|
| 1065 | </hr> | 
|---|
| 1066 | <!-- eof --> | 
|---|
| 1067 | <p><address><hr><div align=center> | 
|---|
| 1068 | <table width=100% cellspacing=0 border=0><tr> | 
|---|
| 1069 | <td>Copyright © 2007 | 
|---|
| 1070 | <a href="troll.html">Trolltech</a><td align=center><a href="trademarks.html">Trademarks</a> | 
|---|
| 1071 | <td align=right><div align=right>Qt 3.3.8</div> | 
|---|
| 1072 | </table></div></address></body> | 
|---|
| 1073 | </html> | 
|---|