0
|
1 |
/****************************************************************************
|
|
2 |
**
|
|
3 |
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
4 |
** All rights reserved.
|
|
5 |
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
6 |
**
|
|
7 |
** This file is part of the documentation of the Qt Toolkit.
|
|
8 |
**
|
|
9 |
** $QT_BEGIN_LICENSE:LGPL$
|
|
10 |
** No Commercial Usage
|
|
11 |
** This file contains pre-release code and may not be distributed.
|
|
12 |
** You may use this file in accordance with the terms and conditions
|
|
13 |
** contained in the Technology Preview License Agreement accompanying
|
|
14 |
** this package.
|
|
15 |
**
|
|
16 |
** GNU Lesser General Public License Usage
|
|
17 |
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
18 |
** General Public License version 2.1 as published by the Free Software
|
|
19 |
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
20 |
** packaging of this file. Please review the following information to
|
|
21 |
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
22 |
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
23 |
**
|
|
24 |
** In addition, as a special exception, Nokia gives you certain additional
|
|
25 |
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
26 |
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
27 |
**
|
|
28 |
** If you have questions regarding the use of this file, please contact
|
|
29 |
** Nokia at qt-info@nokia.com.
|
|
30 |
**
|
|
31 |
**
|
|
32 |
**
|
|
33 |
**
|
|
34 |
**
|
|
35 |
**
|
|
36 |
**
|
|
37 |
**
|
|
38 |
** $QT_END_LICENSE$
|
|
39 |
**
|
|
40 |
****************************************************************************/
|
|
41 |
|
|
42 |
/*!
|
|
43 |
\page activeqt-server.html
|
|
44 |
\title Building ActiveX servers and controls with Qt
|
|
45 |
|
|
46 |
\brief The QAxServer module is a Windows-only static library that
|
|
47 |
you can use to turn a standard Qt binary into a COM server.
|
|
48 |
|
|
49 |
The QAxServer module is part of the \l ActiveQt framework. It
|
|
50 |
consists of three classes:
|
|
51 |
|
|
52 |
\list
|
|
53 |
\o QAxFactory defines a factory for the creation of COM objects.
|
|
54 |
\o QAxBindable provides an interface between the Qt widget and the
|
|
55 |
COM object.
|
|
56 |
\o QAxAggregated can be subclassed to implement additional COM interfaces.
|
|
57 |
\endlist
|
|
58 |
|
|
59 |
Some \l{ActiveQt Examples}{example implementations} of ActiveX
|
|
60 |
controls and COM objects are provided.
|
|
61 |
|
|
62 |
\sa {ActiveQt Framework}
|
|
63 |
|
|
64 |
Topics:
|
|
65 |
|
|
66 |
\tableofcontents
|
|
67 |
|
|
68 |
\section1 Using the Library
|
|
69 |
|
|
70 |
To turn a standard Qt application into a COM server using the
|
|
71 |
QAxServer library you must add \c qaxserver as a CONFIG setting
|
|
72 |
in your \c .pro file.
|
|
73 |
|
|
74 |
An out-of-process executable server is generated from a \c .pro
|
|
75 |
file like this:
|
|
76 |
|
|
77 |
\snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 0
|
|
78 |
|
|
79 |
To build an in-process server, use a \c .pro file like this:
|
|
80 |
\snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 1
|
|
81 |
|
|
82 |
The files \c qaxserver.rc and \c qaxserver.def are part of the
|
|
83 |
framework and can be used from their usual location (specify a
|
|
84 |
path in the \c .pro file), or copied into the project directory.
|
|
85 |
You can modify these files as long as it includes any file as the
|
|
86 |
type library entry, ie. you can add version information or specify
|
|
87 |
a different toolbox icon.
|
|
88 |
|
|
89 |
The \c qaxserver configuration will cause the \c qmake tool to add the
|
|
90 |
required build steps to the build system:
|
|
91 |
|
|
92 |
\list
|
|
93 |
\o Link the binary against \c qaxserver.lib instead of \c qtmain.lib
|
|
94 |
\o Call the \l idc tool to generate an IDL file for the COM server
|
|
95 |
\o Compile the IDL into a type library using the MIDL tool (part of the
|
|
96 |
compiler installation)
|
|
97 |
\o Attach the resulting type library as a binary resource to the server
|
|
98 |
binary (again using the \l idc tool)
|
|
99 |
\o Register the server
|
|
100 |
\endlist
|
|
101 |
|
|
102 |
Note that the QAxServer build system is not supported on Windows 98/ME
|
|
103 |
(attaching of resources to a binary is not possible there), but a server
|
|
104 |
built on Windows NT/2000/XP will work on previous Windows versions as well.
|
|
105 |
|
|
106 |
To skip the post-processing step, also set the \c qaxserver_no_postlink
|
|
107 |
configuration.
|
|
108 |
|
|
109 |
Additionally you can specify a version number using the \c VERSION
|
|
110 |
variable, e.g.
|
|
111 |
|
|
112 |
\snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 2
|
|
113 |
|
|
114 |
The version number specified will be used as the version of the type
|
|
115 |
library and of the server when registering.
|
|
116 |
|
|
117 |
\section2 Out-of-Process vs. In-Process
|
|
118 |
|
|
119 |
Whether your COM server should run as a stand-alone executable
|
|
120 |
or as a shared library in the client process depends mainly on the
|
|
121 |
type of COM objects you want to provide in the server.
|
|
122 |
|
|
123 |
An executable server has the advantage of being able to run as a
|
|
124 |
stand-alone application, but adds considerable overhead to the
|
|
125 |
communication between the COM client and the COM object. If the
|
|
126 |
control has a programming error only the server process running
|
|
127 |
the control will crash, and the client application will probably
|
|
128 |
continue to run. Not all COM clients support executable servers.
|
|
129 |
|
|
130 |
An in-process server is usually smaller and has faster startup
|
|
131 |
time. The communication between client and server is done directly
|
|
132 |
through virtual function calls and does not introduce the overhead
|
|
133 |
required for remote procedure calls. However, if the server crashes the
|
|
134 |
client application is likely to crash as well, and not every
|
|
135 |
functionality is available for in-process servers (i.e. register in
|
|
136 |
the COM's running-object-table).
|
|
137 |
|
|
138 |
Both server types can use Qt either as a shared library, or statically
|
|
139 |
linked into the server binary.
|
|
140 |
|
|
141 |
\section2 Typical Errors During the Post-Build Steps
|
|
142 |
|
|
143 |
For the ActiveQt specific post-processing steps to work the
|
|
144 |
server has to meet some requirements:
|
|
145 |
|
|
146 |
\list
|
|
147 |
\o All controls exposed can be created with nothing but a QApplication
|
|
148 |
instance being present
|
|
149 |
\o The initial linking of the server includes a temporary type
|
|
150 |
library resource
|
|
151 |
\o All dependencies required to run the server are in the system path
|
|
152 |
(or in the path used by the calling environment; note that Visual
|
|
153 |
Studio has its own set of environment variables listed in the
|
|
154 |
Tools|Options|Directories dialog).
|
|
155 |
\endlist
|
|
156 |
|
|
157 |
If those requirements are not met one ore more of the following
|
|
158 |
errors are likely to occur:
|
|
159 |
|
|
160 |
\section3 The Server Executable Crashes
|
|
161 |
|
|
162 |
To generate the IDL the widgets exposed as ActiveX controls need to
|
|
163 |
be instantiated (the constructor is called). At this point, nothing
|
|
164 |
else but a QApplication object exists. Your widget constructor must
|
|
165 |
not rely on any other objects to be created, e.g. it should check for
|
|
166 |
null-pointers.
|
|
167 |
|
|
168 |
To debug your server run it with -dumpidl outputfile and check where
|
|
169 |
it crashes.
|
|
170 |
|
|
171 |
Note that no functions of the control are called.
|
|
172 |
|
|
173 |
\section3 The Server Executable Is Not a Valid Win32 Application
|
|
174 |
|
|
175 |
Attaching the type library corrupted the server binary. This is a
|
|
176 |
bug in Windows and happens only with release builds.
|
|
177 |
|
|
178 |
The first linking step has to link a dummy type library into the
|
|
179 |
executable that can later be replaced by idc. Add a resource file
|
|
180 |
with a type library to your project as demonstrated in the examples.
|
|
181 |
|
|
182 |
\section3 "Unable to locate DLL"
|
|
183 |
|
|
184 |
The build system needs to run the server executable to generate
|
|
185 |
the interface definition, and to register the server. If a dynamic
|
|
186 |
link library the server links against is not in the path this
|
|
187 |
might fail (e.g. Visual Studio calls the server using the
|
|
188 |
enivronment settings specified in the "Directories" option). Make
|
|
189 |
sure that all DLLs required by your server are located in a
|
|
190 |
directory that is listed in the path as printed in the error
|
|
191 |
message box.
|
|
192 |
|
|
193 |
\section3 "Cannot open file ..."
|
|
194 |
|
|
195 |
The ActiveX server could not shut down properly when the last
|
|
196 |
client stopped using it. It usually takes about two seconds for
|
|
197 |
the application to terminate, but you might have to use the task
|
|
198 |
manager to kill the process (e.g. when a client doesn't release
|
|
199 |
the controls properly).
|
|
200 |
|
|
201 |
\section1 Implementing Controls
|
|
202 |
|
|
203 |
To implement a COM object with Qt, create a subclass of QObject
|
|
204 |
or any existing QObject subclass. If the class is a subclass of QWidget,
|
|
205 |
the COM object will be an ActiveX control.
|
|
206 |
|
|
207 |
\snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 3
|
|
208 |
|
|
209 |
The Q_OBJECT macro is required to provide the meta object information
|
|
210 |
about the widget to the ActiveQt framework.
|
|
211 |
|
|
212 |
\snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 4
|
|
213 |
|
|
214 |
Use the Q_CLASSINFO() macro to specify the COM identifiers for the COM
|
|
215 |
object. \c ClassID and \c InterfaceID are required, while \c EventsID is
|
|
216 |
only necessary when your object has signals. To generate these identifiers,
|
|
217 |
use system tools like \c uuidgen or \c guidgen.
|
|
218 |
|
|
219 |
You can specify additional attributes for each of your classes; see
|
|
220 |
\l{Class Information and Tuning} for details.
|
|
221 |
|
|
222 |
\snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 5
|
|
223 |
|
|
224 |
Use the Q_PROPERTY() macro to declare properties for the ActiveX control.
|
|
225 |
|
|
226 |
Declare a standard constructor taking a parent object, and functions,
|
|
227 |
signals and slots like for any QObject subclass.
|
|
228 |
\footnote
|
|
229 |
If a standard constructor is not present the compiler will issue
|
|
230 |
an error "no overloaded function takes 2 parameters" when using
|
|
231 |
the default factory through the QAXFACTORY_DEFAULT() macro. If you
|
|
232 |
cannot provide a standard constructor you must implement a
|
|
233 |
QAxFactory custom factory and call the constructor you have in
|
|
234 |
your implementation of QAxFactory::create.
|
|
235 |
\endfootnote
|
|
236 |
|
|
237 |
\snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 6
|
|
238 |
|
|
239 |
The ActiveQt framework will expose properties and public slots as ActiveX
|
|
240 |
properties and methods, and signals as ActiveX events, and convert between
|
|
241 |
the Qt data types and the equivalent COM data types.
|
|
242 |
|
|
243 |
\section2 Data Types
|
|
244 |
|
|
245 |
The Qt data types that are supported for properties are:
|
|
246 |
|
|
247 |
\table
|
|
248 |
\header
|
|
249 |
\o Qt data type
|
|
250 |
\o COM property
|
|
251 |
\row
|
|
252 |
\o bool
|
|
253 |
\o VARIANT_BOOL
|
|
254 |
\row
|
|
255 |
\o QString
|
|
256 |
\o BSTR
|
|
257 |
\row
|
|
258 |
\o int
|
|
259 |
\o int
|
|
260 |
\row
|
|
261 |
\o uint
|
|
262 |
\o unsigned int
|
|
263 |
\row
|
|
264 |
\o double
|
|
265 |
\o double
|
|
266 |
\row
|
|
267 |
\o \l qlonglong
|
|
268 |
\o CY
|
|
269 |
\row
|
|
270 |
\o \l qulonglong
|
|
271 |
\o CY
|
|
272 |
\row
|
|
273 |
\o QColor
|
|
274 |
\o OLE_COLOR
|
|
275 |
\row
|
|
276 |
\o QDate
|
|
277 |
\o DATE
|
|
278 |
\row
|
|
279 |
\o QDateTime
|
|
280 |
\o DATE
|
|
281 |
\row
|
|
282 |
\o QTime
|
|
283 |
\o DATE
|
|
284 |
\row
|
|
285 |
\o QFont
|
|
286 |
\o IFontDisp*
|
|
287 |
\row
|
|
288 |
\o QPixmap
|
|
289 |
\o IPictureDisp*
|
|
290 |
\footnote
|
|
291 |
COM cannot marshal IPictureDisp accross process boundaries,
|
|
292 |
so QPixmap properties cannot be called for out-of-process servers. You
|
|
293 |
can however marshal the image data via e.g. temporary files. See the
|
|
294 |
Microsoft
|
|
295 |
\link http://support.microsoft.com/default.aspx?scid=kb;[LN];Q150034 KB article
|
|
296 |
Q150034 \endlink for more information.
|
|
297 |
\endfootnote
|
|
298 |
\row
|
|
299 |
\o QVariant
|
|
300 |
\o VARIANT
|
|
301 |
\row
|
|
302 |
\o QVariantList (same as QList\<QVariant\>)
|
|
303 |
\o SAFEARRAY(VARIANT)
|
|
304 |
\row
|
|
305 |
\o QStringList
|
|
306 |
\o SAFEARRAY(BSTR)
|
|
307 |
\row
|
|
308 |
\o QByteArray
|
|
309 |
\o SAFEARRAY(BYTE)
|
|
310 |
\row
|
|
311 |
\o QRect
|
|
312 |
\o User defined type
|
|
313 |
\row
|
|
314 |
\o QSize
|
|
315 |
\o User defined type
|
|
316 |
\row
|
|
317 |
\o QPoint
|
|
318 |
\o User defined type
|
|
319 |
\endtable
|
|
320 |
|
|
321 |
The Qt data types that are supported for parameters in signals and
|
|
322 |
slots are:
|
|
323 |
\table
|
|
324 |
\header
|
|
325 |
\o Qt data type
|
|
326 |
\o COM parameter
|
|
327 |
\row
|
|
328 |
\o bool
|
|
329 |
\o [in] VARIANT_BOOL
|
|
330 |
\row
|
|
331 |
\o bool&
|
|
332 |
\o [in, out] VARIANT_BOOL*
|
|
333 |
\row
|
|
334 |
\o QString, const QString&
|
|
335 |
\o [in] BSTR
|
|
336 |
\row
|
|
337 |
\o QString&
|
|
338 |
\o [in, out] BSTR*
|
|
339 |
\row
|
|
340 |
\o QString&
|
|
341 |
\o [in, out] BSTR*
|
|
342 |
\row
|
|
343 |
\o int
|
|
344 |
\o [in] int
|
|
345 |
\row
|
|
346 |
\o int&
|
|
347 |
\o [in,out] int
|
|
348 |
\row
|
|
349 |
\o uint
|
|
350 |
\o [in] unsigned int
|
|
351 |
\row
|
|
352 |
\o uint&
|
|
353 |
\o [in, out] unsigned int*
|
|
354 |
\row
|
|
355 |
\o double
|
|
356 |
\o [in] double
|
|
357 |
\row
|
|
358 |
\o double&
|
|
359 |
\o [in, out] double*
|
|
360 |
\row
|
|
361 |
\o QColor, const QColor&
|
|
362 |
\o [in] OLE_COLOR
|
|
363 |
\row
|
|
364 |
\o QColor&
|
|
365 |
\o [in, out] OLE_COLOR*
|
|
366 |
\row
|
|
367 |
\o QDate, const QDate&
|
|
368 |
\o [in] DATE
|
|
369 |
\row
|
|
370 |
\o QDate&
|
|
371 |
\o [in, out] DATE*
|
|
372 |
\row
|
|
373 |
\o QDateTime, const QDateTime&
|
|
374 |
\o [in] DATE
|
|
375 |
\row
|
|
376 |
\o QDateTime&
|
|
377 |
\o [in, out] DATE*
|
|
378 |
\row
|
|
379 |
\o QFont, const QFont&
|
|
380 |
\o [in] IFontDisp*
|
|
381 |
\row
|
|
382 |
\o QFont&
|
|
383 |
\o [in, out] IFontDisp**
|
|
384 |
\row
|
|
385 |
\o QPixmap, const QPixmap&
|
|
386 |
\o [in] IPictureDisp*
|
|
387 |
\row
|
|
388 |
\o QPixmap&
|
|
389 |
\o [in, out] IPictureDisp**
|
|
390 |
\row
|
|
391 |
\o QList\<QVariant\>, const QList\<QVariant\>&
|
|
392 |
\o [in] SAFEARRAY(VARIANT)
|
|
393 |
\row
|
|
394 |
\o QList\<QVariant\>&
|
|
395 |
\o [in, out] SAFEARRAY(VARIANT)*
|
|
396 |
\row
|
|
397 |
\o QStringList, const QStringList&
|
|
398 |
\o [in] SAFEARRAY(BSTR)
|
|
399 |
\row
|
|
400 |
\o QStringList&
|
|
401 |
\o [in, out] SAFEARRAY(BSTR)*
|
|
402 |
\row
|
|
403 |
\o QByteArray, const QByteArray&
|
|
404 |
\o [in] SAFEARRAY(BYTE)
|
|
405 |
\row
|
|
406 |
\o QByteArray&
|
|
407 |
\o [in, out] SAFEARRAY(BYTE)*
|
|
408 |
\row
|
|
409 |
\o QObject*
|
|
410 |
\o [in] IDispatch*
|
|
411 |
\row
|
|
412 |
\o QRect&
|
|
413 |
\footnote
|
|
414 |
OLE needs to marshal user defined types by reference (ByRef), and cannot
|
|
415 |
marshal them by value (ByVal). This is why const-references and object
|
|
416 |
parameters are not supported for QRect, QSize and QPoint. Also note that
|
|
417 |
servers with this datatype require Windows 98 or DCOM 1.2 to be installed.
|
|
418 |
\endfootnote
|
|
419 |
\o [in, out] struct QRect (user defined)
|
|
420 |
\row
|
|
421 |
\o QSize&
|
|
422 |
\o [in, out] struct QSize (user defined)
|
|
423 |
\row
|
|
424 |
\o QPoint&
|
|
425 |
\o [in, out] struct QPoint (user defined)
|
|
426 |
\endtable
|
|
427 |
|
|
428 |
Also supported are exported enums and flags (see Q_ENUMS() and
|
|
429 |
Q_FLAGS()). The in-parameter types are also supported as
|
|
430 |
return values.
|
|
431 |
|
|
432 |
Properties and signals/slots that have parameters using any other
|
|
433 |
data types are ignored by the ActiveQt framework.
|
|
434 |
|
|
435 |
\section2 Sub-Objects
|
|
436 |
|
|
437 |
COM objects can have multiple sub-objects that can represent a sub element
|
|
438 |
of the COM object. A COM object representing a multi-document spread sheet
|
|
439 |
application can for example provide one sub-object for each spread sheet.
|
|
440 |
|
|
441 |
Any QObject subclass can be used as the type for a sub object in ActiveX, as
|
|
442 |
long as it is known to the QAxFactory. Then the type can be used in properties,
|
|
443 |
or as the return type or paramter of a slot.
|
|
444 |
|
|
445 |
\section2 Property Notification
|
|
446 |
|
|
447 |
To make the properties bindable for the ActiveX client, use multiple
|
|
448 |
inheritance from the QAxBindable class:
|
|
449 |
|
|
450 |
\snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 7
|
|
451 |
|
|
452 |
When implementing the property write functions, use the
|
|
453 |
QAxBindable class's requestPropertyChange() and propertyChanged()
|
|
454 |
functions to allow ActiveX clients to bind to the control
|
|
455 |
properties.
|
|
456 |
\footnote
|
|
457 |
This is not required, but gives the client more control over
|
|
458 |
the ActiveX control.
|
|
459 |
\endfootnote
|
|
460 |
|
|
461 |
\section1 Serving Controls
|
|
462 |
|
|
463 |
To make a COM server available to the COM system it must be registered
|
|
464 |
in the system registry using five unique identifiers.
|
|
465 |
These identifiers are provided by tools like \c guidgen or \c uuidgen.
|
|
466 |
The registration information allows COM to localize the binary providing
|
|
467 |
a requested ActiveX control, marshall remote procedure calls to the
|
|
468 |
control and read type information about the methods and properties exposed
|
|
469 |
by the control.
|
|
470 |
|
|
471 |
To create the COM object when the client asks for it the server must export
|
|
472 |
an implementation of a QAxFactory. The easist way to do this is to use a set
|
|
473 |
of macros:
|
|
474 |
|
|
475 |
\snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 8
|
|
476 |
|
|
477 |
This will export \c MyWidget and \c MyWidget2 as COM objects that can be
|
|
478 |
created by COM clients, and will register \c MySubType as a type that can
|
|
479 |
be used in properties and parameters of \c MyWidget and \c MyWidget2.
|
|
480 |
|
|
481 |
The \link QAxFactory QAxFactory class documentation \endlink explains
|
|
482 |
how to use this macro, and how to implement and use custom factories.
|
|
483 |
|
|
484 |
For out-of-process executable servers you can implement a main()
|
|
485 |
function to instantiate a QApplication object and enter the event
|
|
486 |
loop just like any normal Qt application. By default the
|
|
487 |
application will start as a standard Qt application, but if you
|
|
488 |
pass \c -activex on the command line it will start as an ActiveX
|
|
489 |
server. Use QAxFactory::isServer() to create and run a standard
|
|
490 |
application interface, or to prevent a stand-alone execution:
|
|
491 |
|
|
492 |
\snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 9
|
|
493 |
|
|
494 |
This is however not necessary as ActiveQt provides a default implementation
|
|
495 |
of a main function. The default implemenation calls QAxFactory::startServer(),
|
|
496 |
creates a QApplication instance and calls exec().
|
|
497 |
|
|
498 |
To build the ActiveX server executable run \c qmake
|
|
499 |
to generate the makefile, and use your compiler's
|
|
500 |
make tool as for any other Qt application. The make process will
|
|
501 |
also register the controls in the system registry by calling the
|
|
502 |
resulting executable with the \c -regserver command line option.
|
|
503 |
|
|
504 |
If the ActiveX server is an executable, the following command line
|
|
505 |
options are supported:
|
|
506 |
\table
|
|
507 |
\header \o Option \o Result
|
|
508 |
\row \o \c -regserver \o Registers the server in the system registry
|
|
509 |
\row \o \c -unregserver \o Unregisters the server from the system registry
|
|
510 |
\row \o \c -activex \o Starts the application as an ActiveX server
|
|
511 |
\row \o \c{-dumpidl <file> -version x.y} \o Writes the server's IDL to the
|
|
512 |
specified file. The type library will have version x.y
|
|
513 |
\endtable
|
|
514 |
|
|
515 |
In-process servers can be registered using the \c regsvr32 tool available
|
|
516 |
on all Windows systems.
|
|
517 |
|
|
518 |
\section2 Typical Compile-Time Problems
|
|
519 |
|
|
520 |
The compiler/linker errors listed are based on those issued by the
|
|
521 |
Microsoft Visual C++ 6.0 compiler.
|
|
522 |
|
|
523 |
\section3 "No overloaded function takes 2 parameters"
|
|
524 |
|
|
525 |
When the error occurs in code that uses the QAXFACTORY_DEFAULT()
|
|
526 |
macro, the widget class had no constructor that can be used by the
|
|
527 |
default factory. Either add a standard widget constructor or
|
|
528 |
implement a custom factory that doesn't require one.
|
|
529 |
|
|
530 |
When the error occurs in code that uses the QAXFACTORY_EXPORT()
|
|
531 |
macro, the QAxFactory subclass had no appropriate constructor.
|
|
532 |
Provide a public class constructor like
|
|
533 |
|
|
534 |
\snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 10
|
|
535 |
|
|
536 |
for your factory class.
|
|
537 |
|
|
538 |
\section3 "Syntax error: bad suffix on number"
|
|
539 |
|
|
540 |
The unique identifiers have not been passed as strings into the
|
|
541 |
QAXFACTORY_EXPORT() or QAXFACTORY_DEFAULT() macro.
|
|
542 |
|
|
543 |
\section3 "Unresolved external symbol _ucm_instantiate"
|
|
544 |
|
|
545 |
The server does not export an implementation of a QAxFactory. Use
|
|
546 |
the QAXFACTORY_EXPORT() macro in one of the project's
|
|
547 |
implementation files to instantiate and export a factory, or use
|
|
548 |
the QAXFACTORY_DEFAULT() macro to use the default factory.
|
|
549 |
|
|
550 |
\section3 "_ucm_initialize already defined in ..."
|
|
551 |
|
|
552 |
The server exports more than one implementation of a QAxFactory,
|
|
553 |
or exports the same implementation twice. If you use the default
|
|
554 |
factory, the QAXFACTORY_DEFAULT() macro must only be used once in
|
|
555 |
the project. Use a custom QAxFactory implementation and the
|
|
556 |
QAXFACTORY_EXPORT() macro if the server provides multiple ActiveX
|
|
557 |
controls.
|
|
558 |
|
|
559 |
\section2 Distributing QAxServer Binaries
|
|
560 |
|
|
561 |
ActiveX servers written with Qt can use Qt either as a shared
|
|
562 |
library, or have Qt linked statically into the binary. Both ways
|
|
563 |
will produce rather large packages (either the server binary
|
|
564 |
itself becomes large, or you have to ship the Qt DLL).
|
|
565 |
|
|
566 |
\section3 Installing Stand-Alone Servers
|
|
567 |
|
|
568 |
When your ActiveX server can also run as a stand-alone application,
|
|
569 |
run the server executable with the \c -regserver command line
|
|
570 |
parameter after installing the executable on the target system.
|
|
571 |
After that the controls provided by the server will be available to
|
|
572 |
ActiveX clients.
|
|
573 |
|
|
574 |
\section3 Installing In-Process Servers
|
|
575 |
|
|
576 |
When your ActiveX server is part of an installation package, use the
|
|
577 |
\c regsvr32 tool provided by Microsoft to register the controls on
|
|
578 |
the target system. If this tool is not present, load the DLL into
|
|
579 |
your installer process, resolve the \c DllRegisterServer symbol and
|
|
580 |
call the function:
|
|
581 |
|
|
582 |
\snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 11
|
|
583 |
|
|
584 |
\section3 Distributing Servers over the Internet
|
|
585 |
|
|
586 |
If you want to use controls in your server in web-pages you need to
|
|
587 |
make the server available to the browser used to view your page, and
|
|
588 |
you need to specify the location of the server package in your page.
|
|
589 |
|
|
590 |
To specify the location of a server, use the CODEBASE attribute in
|
|
591 |
the OBJECT tag of your web-site. The value can point to the server
|
|
592 |
file itself, to an INF file listing other files the server requires
|
|
593 |
(e.g. the Qt DLL), or a compressed CAB archive.
|
|
594 |
|
|
595 |
INF and CAB files are documented in almost every book available about
|
|
596 |
ActiveX and COM programming as well as in the MSDN library and various
|
|
597 |
other Online resources. The examples include INF files that can be used
|
|
598 |
to build CAB archives:
|
|
599 |
|
|
600 |
\snippet examples/activeqt/simple/simple.inf 0
|
|
601 |
|
|
602 |
The CABARC tool from Microsoft can easily generate CAB archives:
|
|
603 |
|
|
604 |
\snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 12
|
|
605 |
|
|
606 |
The INF files assume a static build of Qt, so no dependencies to other DLLs
|
|
607 |
are listed in the INF files. To distribute an ActiveX server depending on
|
|
608 |
DLLs you must add the dependencies, and provide the library files
|
|
609 |
with the archive.
|
|
610 |
|
|
611 |
\section1 Using the Controls
|
|
612 |
|
|
613 |
To use the ActiveX controls, e.g. to embed them in a web page, use
|
|
614 |
the \c <object> HTML tag.
|
|
615 |
|
|
616 |
\snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 13
|
|
617 |
|
|
618 |
To initialize the control's properties, use
|
|
619 |
|
|
620 |
\snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 14
|
|
621 |
|
|
622 |
If the web browser supports scripting use JavaScript, VBScript
|
|
623 |
and forms to script the control. The
|
|
624 |
\l{ActiveQt Examples} include demonstration HTML pages for the example
|
|
625 |
controls.
|
|
626 |
|
|
627 |
\section2 Supported and Unsupported ActiveX Clients
|
|
628 |
|
|
629 |
The following is largly based on our own experiements with ActiveX
|
|
630 |
controls and client applications, and is by no means complete.
|
|
631 |
|
|
632 |
\section3 Supported Clients
|
|
633 |
|
|
634 |
These standard applications work with ActiveX controls developed with
|
|
635 |
ActiveQt. Note that some clients support only in-process controls.
|
|
636 |
|
|
637 |
\list
|
|
638 |
\o Internet Explorer
|
|
639 |
\o Microsoft ActiveX Control Test Container
|
|
640 |
\o Microsoft Visual Studio 6.0
|
|
641 |
\o Microsoft Visual Studio.NET/2003
|
|
642 |
\o Microsoft Visual Basic 6.0
|
|
643 |
\o MFC- and ATL-based containers
|
|
644 |
\o Sybase PowerBuilder
|
|
645 |
\o ActiveQt based containers
|
|
646 |
\endlist
|
|
647 |
|
|
648 |
Microsoft Office applications are supported, but you need to register
|
|
649 |
the controls as "Insertable" objects. Reimplement QAxFactory::registerClass
|
|
650 |
to add this attribute to the COM class, or set the "Insertable" class info
|
|
651 |
for your class to "yes" using the Q_CLASSINFO macro.
|
|
652 |
|
|
653 |
\section3 Unsupported Clients
|
|
654 |
|
|
655 |
We have not managed to make ActiveQt based COM objects work with the
|
|
656 |
following client applications.
|
|
657 |
|
|
658 |
\list
|
|
659 |
\o Borland C++ Builder (Versions 5 and 6)
|
|
660 |
\o Borland Delphi
|
|
661 |
\endlist
|
|
662 |
|
|
663 |
\section2 Typical Runtime Errors
|
|
664 |
|
|
665 |
\section3 The Server Does Not Respond
|
|
666 |
|
|
667 |
If the system is unable to start the server (check with the task
|
|
668 |
manager whether the server runs a process), make sure that no DLL
|
|
669 |
the server depends on is missing from the system path (e.g. the Qt
|
|
670 |
DLL!). Use a dependency walker to view all dependencies of the server
|
|
671 |
binary.
|
|
672 |
|
|
673 |
If the server runs (e.g. the task manager lists a process), see
|
|
674 |
the following section for information on debugging your server.
|
|
675 |
|
|
676 |
\section3 The Object Cannot Be Created
|
|
677 |
|
|
678 |
If the server could be built and registered correctly during the build
|
|
679 |
process, but the object cannot be initiliazed e.g. by the OLE/COM Object
|
|
680 |
Viewer application, make sure that no DLL the server depends on is
|
|
681 |
missing from the system path (e.g. the Qt DLL). Use a dependency walker
|
|
682 |
to view all dependencies of the server binary.
|
|
683 |
|
|
684 |
If the server runs, see the following section for information on
|
|
685 |
debugging your server.
|
|
686 |
|
|
687 |
\section2 Debugging Runtime Errors
|
|
688 |
|
|
689 |
To debug an in-process server in Visual Studio, set the server project
|
|
690 |
as the active project, and specify a client "executable for debug
|
|
691 |
session" in the project settings (e.g. use the ActiveX Test Container).
|
|
692 |
You can set breakpoints in your code, and also step into ActiveQt and
|
|
693 |
Qt code if you installed the debug version.
|
|
694 |
|
|
695 |
To debug an executable server, run the application in a debugger
|
|
696 |
and start with the command line parameter \c -activex. Then start
|
|
697 |
your client and create an instance of your ActiveX control. COM
|
|
698 |
will use the existing process for the next client trying to create
|
|
699 |
an ActiveX control.
|
|
700 |
|
|
701 |
\section1 Class Information and Tuning
|
|
702 |
|
|
703 |
To provide attributes for each COM class, use the Q_CLASSINFO macro, which is part of
|
|
704 |
Qt's meta object system.
|
|
705 |
|
|
706 |
\table
|
|
707 |
\header
|
|
708 |
\o Key
|
|
709 |
\o Meaning of value
|
|
710 |
\row
|
|
711 |
\o Version
|
|
712 |
\o The version of the class (1.0 is default)
|
|
713 |
\row
|
|
714 |
\o Description
|
|
715 |
\o A string describing the class.
|
|
716 |
\row
|
|
717 |
\o ClassID
|
|
718 |
\o The class ID.
|
|
719 |
You must reimplement QAxFactory::classID if not specified.
|
|
720 |
\row
|
|
721 |
\o InterfaceID
|
|
722 |
\o The interface ID.
|
|
723 |
You must reimplement QAxFactory::interfaceID if not specified.
|
|
724 |
\row
|
|
725 |
\o EventsID
|
|
726 |
\o The event interface ID.
|
|
727 |
No signals are exposed as COM events if not specified.
|
|
728 |
\row
|
|
729 |
\o DefaultProperty
|
|
730 |
\o The property specified represents the default property of this class.
|
|
731 |
Ie. the default property of a push button would be "text".
|
|
732 |
\row
|
|
733 |
\o DefaultSignal
|
|
734 |
\o The signal specified respresents the default signal of this class.
|
|
735 |
Ie. the default signal of a push button would be "clicked".
|
|
736 |
\row
|
|
737 |
\o LicenseKey
|
|
738 |
\o Object creation requires the specified license key. The key can be
|
|
739 |
empty to require a licensed machine. By default classes are not
|
|
740 |
licensed. Also see the following section.
|
|
741 |
\row
|
|
742 |
\o StockEvents
|
|
743 |
\o Objects expose stock events if value is "yes".
|
|
744 |
See \l QAxFactory::hasStockEvents()
|
|
745 |
\row
|
|
746 |
\o ToSuperClass
|
|
747 |
\o Objects expose functionality of all super-classes up to and
|
|
748 |
including the class name in value.
|
|
749 |
See \l QAxFactory::exposeToSuperClass()
|
|
750 |
\row
|
|
751 |
\o Insertable
|
|
752 |
\o If the value is "yes" the class is registered to be "Insertable"
|
|
753 |
and will be listed in OLE 2 containers (ie. Microsoft Office). This
|
|
754 |
attribute is not be set by default.
|
|
755 |
\row
|
|
756 |
\o Aggregatable
|
|
757 |
\o If the value is "no" the class does not support aggregation. By
|
|
758 |
default aggregation is supported.
|
|
759 |
\row
|
|
760 |
\o Creatable
|
|
761 |
\o If the value is "no" the class cannot be created by the client,
|
|
762 |
and is only available through the API of another class (ie. the
|
|
763 |
class is a sub-type).
|
|
764 |
\row
|
|
765 |
\o RegisterObject
|
|
766 |
\o If the value is "yes" objects of this class are registered with
|
|
767 |
OLE and accessible from the running object table (ie. clients
|
|
768 |
can connect to an already running instance of this class). This
|
|
769 |
attribute is only supported in out-of-process servers.
|
|
770 |
\row
|
|
771 |
\o MIME
|
|
772 |
\o The object can handle data and files of the format specified in the
|
|
773 |
value. The value has the format mime:extension:description. Multiple
|
|
774 |
formats are separated by a semicolon.
|
|
775 |
\row
|
|
776 |
\o CoClassAlias
|
|
777 |
\o The classname used in the generated IDL and in the registry. This is
|
|
778 |
esp. useful for C++ classes that live in a namespace - by default,
|
|
779 |
ActiveQt just removes the "::" to make the IDL compile.
|
|
780 |
\endtable
|
|
781 |
|
|
782 |
Note that both keys and values are case sensitive.
|
|
783 |
|
|
784 |
The following declares version 2.0 of a class that exposes only its
|
|
785 |
own API, and is available in the "Insert Objects" dialog of Microsoft
|
|
786 |
Office applications.
|
|
787 |
|
|
788 |
\snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 15
|
|
789 |
|
|
790 |
\section2 Developing Licensed Components
|
|
791 |
|
|
792 |
If you develop components you might want to control who is able to instantiate
|
|
793 |
those components. Since the server binary can be shipped to and registered on
|
|
794 |
any client machine it is possible for anybody to use those components in his
|
|
795 |
own software.
|
|
796 |
|
|
797 |
Licensing components can be done using a variety of techniques, e.g. the code
|
|
798 |
creating the control can provide a license key, or the machine on which the
|
|
799 |
control is supposed to run needs to be licensed.
|
|
800 |
|
|
801 |
To mark a Qt class as licensed specify a "LicenseKey" using the
|
|
802 |
Q_CLASSINFO() macro.
|
|
803 |
|
|
804 |
\snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 16
|
|
805 |
|
|
806 |
The key is required to be able to create an instance of \c MyLicensedControl
|
|
807 |
on a machine that is not licensed itself. The licensed developer can now
|
|
808 |
redistributes the server binary with his application, which creates the control
|
|
809 |
using the value of "LicenseKey", while users of the application cannot create
|
|
810 |
the control without the license key.
|
|
811 |
|
|
812 |
If a single license key for the control is not sufficient (ie. you want
|
|
813 |
differnet developers to receive different license keys) you can specify an
|
|
814 |
empty key to indicate that the control requires a license, and reimplement
|
|
815 |
\l QAxFactory::validateLicenseKey() to verify that a license exists on the
|
|
816 |
system (ie. through a license file).
|
|
817 |
|
|
818 |
\section2 More Interfaces
|
|
819 |
|
|
820 |
ActiveX controls provided by ActiveQt servers support a minimal set of COM
|
|
821 |
interfaces to implement the OLE specifications. When the ActiveX class inherits
|
|
822 |
from the QAxBindable class it can also implement additional COM interfaces.
|
|
823 |
|
|
824 |
Create a new subclass of QAxAggregated and use multiple inheritance
|
|
825 |
to subclass additional COM interface classes.
|
|
826 |
|
|
827 |
\snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 17
|
|
828 |
|
|
829 |
Reimplement the QAxAggregated::queryInterface() function to
|
|
830 |
support the additional COM interfaces.
|
|
831 |
|
|
832 |
\snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 18
|
|
833 |
|
|
834 |
Since \c ISomeCOMInterface is a subclass of \c IUnknown you will
|
|
835 |
have to implement the \c QueryInterface(), \c AddRef(), and \c
|
|
836 |
Release() functions. Use the QAXAGG_IUNKNOWN macro in your
|
|
837 |
class definition to do that. If you implement the \c IUnknown
|
|
838 |
functions manually, delegate the calls to the interface pointer
|
|
839 |
returned by the QAxAggregated::controllingUnknown() function,
|
|
840 |
e.g.
|
|
841 |
|
|
842 |
\snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 19
|
|
843 |
|
|
844 |
Do not support the \c IUnknown interface itself in your
|
|
845 |
\l{QAxAggregated::queryInterface()}{queryInterface()}
|
|
846 |
implementation.
|
|
847 |
|
|
848 |
Implement the methods of the COM interfaces, and use QAxAggregated::object()
|
|
849 |
if you need to make calls to the QObject subclass implementing the control.
|
|
850 |
|
|
851 |
In your QAxBindable subclass, implement
|
|
852 |
QAxBindable::createAggregate() to return a new object of the
|
|
853 |
QAxAggregated subclass.
|
|
854 |
|
|
855 |
\snippet doc/src/snippets/code/doc_src_qaxserver.qdoc 20
|
|
856 |
*/
|