|
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 ActiveQt framework of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:BSD$ |
|
10 ** You may use this file under the terms of the BSD license as follows: |
|
11 ** |
|
12 ** "Redistribution and use in source and binary forms, with or without |
|
13 ** modification, are permitted provided that the following conditions are |
|
14 ** met: |
|
15 ** * Redistributions of source code must retain the above copyright |
|
16 ** notice, this list of conditions and the following disclaimer. |
|
17 ** * Redistributions in binary form must reproduce the above copyright |
|
18 ** notice, this list of conditions and the following disclaimer in |
|
19 ** the documentation and/or other materials provided with the |
|
20 ** distribution. |
|
21 ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor |
|
22 ** the names of its contributors may be used to endorse or promote |
|
23 ** products derived from this software without specific prior written |
|
24 ** permission. |
|
25 ** |
|
26 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
27 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
28 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
29 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
30 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
31 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
32 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
33 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
34 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
35 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
36 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." |
|
37 ** $QT_END_LICENSE$ |
|
38 ** |
|
39 ****************************************************************************/ |
|
40 |
|
41 #include "qaxfactory.h" |
|
42 |
|
43 #ifndef QT_NO_WIN_ACTIVEQT |
|
44 |
|
45 #include <qfile.h> |
|
46 #include <qfileinfo.h> |
|
47 #include <qmetaobject.h> |
|
48 #include <qsettings.h> |
|
49 #include <qwidget.h> |
|
50 #include <qt_windows.h> |
|
51 |
|
52 QT_BEGIN_NAMESPACE |
|
53 |
|
54 extern wchar_t qAxModuleFilename[MAX_PATH]; |
|
55 |
|
56 /*! |
|
57 \class QAxFactory |
|
58 \brief The QAxFactory class defines a factory for the creation of COM components. |
|
59 |
|
60 \inmodule QAxServer |
|
61 |
|
62 Implement this factory once in your COM server to provide information |
|
63 about the components the server can create. Subclass QAxFactory and implement |
|
64 the pure virtual functions in any implementation file (e.g. main.cpp), and export |
|
65 the factory using the \c QAXFACTORY_EXPORT() macro. |
|
66 |
|
67 \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 0 |
|
68 |
|
69 If you use the \c Q_CLASSINFO() macro to provide the unique |
|
70 identifiers or other attributes for your class you can use the \c |
|
71 QAXFACTORY_BEGIN(), \c QAXCLASS() and \c QAXFACTORY_END() macros to |
|
72 expose one or more classes as COM objects. |
|
73 |
|
74 \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 1 |
|
75 |
|
76 |
|
77 If your server supports just a single COM object, you can use |
|
78 a default factory implementation through the \c QAXFACTORY_DEFAULT() macro. |
|
79 |
|
80 \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 2 |
|
81 |
|
82 Only one QAxFactory implementation may be instantiated and |
|
83 exported by an ActiveX server application. This instance is accessible |
|
84 through the global qAxFactory() function. |
|
85 |
|
86 A factory can also reimplement the registerClass() and |
|
87 unregisterClass() functions to set additional flags for an ActiveX |
|
88 control in the registry. To limit the number of methods or |
|
89 properties a widget class exposes from its parent classes |
|
90 reimplement exposeToSuperClass(). |
|
91 |
|
92 \sa QAxAggregated, QAxBindable, {ActiveQt Framework} |
|
93 */ |
|
94 |
|
95 /*! |
|
96 Constructs a QAxFactory object that returns \a libid and \a appid |
|
97 in the implementation of the respective interface functions. |
|
98 */ |
|
99 |
|
100 QAxFactory::QAxFactory(const QUuid &libid, const QUuid &appid) |
|
101 : typelib(libid), app(appid) |
|
102 { |
|
103 } |
|
104 |
|
105 /*! |
|
106 Destroys the QAxFactory object. |
|
107 */ |
|
108 QAxFactory::~QAxFactory() |
|
109 { |
|
110 } |
|
111 |
|
112 /*! |
|
113 \fn QUuid QAxFactory::typeLibID() const |
|
114 |
|
115 Reimplement this function to return the ActiveX server's type |
|
116 library identifier. |
|
117 */ |
|
118 QUuid QAxFactory::typeLibID() const |
|
119 { |
|
120 return typelib; |
|
121 } |
|
122 |
|
123 /*! |
|
124 \fn QUuid QAxFactory::appID() const |
|
125 |
|
126 Reimplement this function to return the ActiveX server's |
|
127 application identifier. |
|
128 */ |
|
129 QUuid QAxFactory::appID() const |
|
130 { |
|
131 return app; |
|
132 } |
|
133 |
|
134 /*! |
|
135 \fn QStringList QAxFactory::featureList() const |
|
136 |
|
137 Reimplement this function to return a list of the widgets (class |
|
138 names) supported by this factory. |
|
139 */ |
|
140 |
|
141 /*! |
|
142 \fn QObject *QAxFactory::createObject(const QString &key) |
|
143 |
|
144 Reimplement this function to return a new object for \a key, or 0 if |
|
145 this factory doesn't support the value of \a key. |
|
146 |
|
147 If the object returned is a QWidget it will be exposed as an ActiveX |
|
148 control, otherwise the returned object will be exposed as a simple COM |
|
149 object. |
|
150 */ |
|
151 |
|
152 /*! |
|
153 \fn const QMetaObject *QAxFactory::metaObject(const QString &key) const |
|
154 |
|
155 Reimplement this function to return the QMetaObject corresponding to |
|
156 \a key, or 0 if this factory doesn't support the value of \a key. |
|
157 */ |
|
158 |
|
159 /*! |
|
160 \fn bool QAxFactory::createObjectWrapper(QObject *object, IDispatch **wrapper) |
|
161 |
|
162 Reimplement this function to provide the COM object for \a object |
|
163 in \a wrapper. Return true if the function was successful; otherwise |
|
164 return false. |
|
165 |
|
166 The default implementation creates a generic automation wrapper based |
|
167 on the meta object information of \a object. |
|
168 */ |
|
169 // implementation in qaxserverbase.cpp |
|
170 |
|
171 /*! |
|
172 Reimplement this function to return the class identifier for each |
|
173 \a key returned by the featureList() implementation, or an empty |
|
174 QUuid if this factory doesn't support the value of \a key. |
|
175 |
|
176 The default implementation interprets \a key as the class name, |
|
177 and returns the value of the Q_CLASSINFO() entry "ClassID". |
|
178 */ |
|
179 QUuid QAxFactory::classID(const QString &key) const |
|
180 { |
|
181 const QMetaObject *mo = metaObject(key); |
|
182 if (!mo) |
|
183 return QUuid(); |
|
184 QString id = QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("ClassID")).value()); |
|
185 |
|
186 return QUuid(id); |
|
187 } |
|
188 |
|
189 /*! |
|
190 Reimplement this function to return the interface identifier for |
|
191 each \a key returned by the featureList() implementation, or an |
|
192 empty QUuid if this factory doesn't support the value of \a key. |
|
193 |
|
194 The default implementation interprets \a key as the class name, |
|
195 and returns the value of the Q_CLASSINFO() entry "InterfaceID". |
|
196 */ |
|
197 QUuid QAxFactory::interfaceID(const QString &key) const |
|
198 { |
|
199 const QMetaObject *mo = metaObject(key); |
|
200 if (!mo) |
|
201 return QUuid(); |
|
202 QString id = QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("InterfaceID")).value()); |
|
203 |
|
204 return QUuid(id); |
|
205 } |
|
206 |
|
207 /*! |
|
208 Reimplement this function to return the identifier of the event |
|
209 interface for each \a key returned by the featureList() |
|
210 implementation, or an empty QUuid if this factory doesn't support |
|
211 the value of \a key. |
|
212 |
|
213 The default implementation interprets \a key as the class name, |
|
214 and returns the value of the Q_CLASSINFO() entry "EventsID". |
|
215 */ |
|
216 QUuid QAxFactory::eventsID(const QString &key) const |
|
217 { |
|
218 const QMetaObject *mo = metaObject(key); |
|
219 if (!mo) |
|
220 return QUuid(); |
|
221 QString id = QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("EventsID")).value()); |
|
222 |
|
223 return QUuid(id); |
|
224 } |
|
225 |
|
226 /*! |
|
227 Registers additional values for the class \a key in the system |
|
228 registry using the \a settings object. The standard values have |
|
229 already been registered by the framework, but additional values, |
|
230 e.g. implemented categories, can be added in an implementation of |
|
231 this function. |
|
232 |
|
233 \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 3 |
|
234 |
|
235 If you reimplement this function you must also reimplement |
|
236 unregisterClass() to remove the additional registry values. |
|
237 |
|
238 \sa QSettings |
|
239 */ |
|
240 void QAxFactory::registerClass(const QString &key, QSettings *settings) const |
|
241 { |
|
242 Q_UNUSED(key); |
|
243 Q_UNUSED(settings) |
|
244 } |
|
245 |
|
246 /*! |
|
247 Unregisters any additional values for the class \a key from the |
|
248 system registry using the \a settings object. |
|
249 |
|
250 \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 4 |
|
251 |
|
252 \sa registerClass(), QSettings |
|
253 */ |
|
254 void QAxFactory::unregisterClass(const QString &key, QSettings *settings) const |
|
255 { |
|
256 Q_UNUSED(key); |
|
257 Q_UNUSED(settings) |
|
258 } |
|
259 |
|
260 /*! |
|
261 Reimplement this function to return true if \a licenseKey is a valid |
|
262 license for the class \a key, or if the current machine is licensed. |
|
263 |
|
264 The default implementation returns true if the class \a key is |
|
265 not licensed (ie. no \c Q_CLASSINFO() attribute "LicenseKey"), or |
|
266 if \a licenseKey matches the value of the "LicenseKey" |
|
267 attribute, or if the machine is licensed through a .LIC file with |
|
268 the same filename as this COM server. |
|
269 */ |
|
270 bool QAxFactory::validateLicenseKey(const QString &key, const QString &licenseKey) const |
|
271 { |
|
272 const QMetaObject *mo = metaObject(key); |
|
273 if (!mo) |
|
274 return true; |
|
275 |
|
276 QString classKey = QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("LicenseKey")).value()); |
|
277 if (classKey.isEmpty()) |
|
278 return true; |
|
279 |
|
280 if (licenseKey.isEmpty()) { |
|
281 QString licFile(QString::fromWCharArray(qAxModuleFilename)); |
|
282 int lastDot = licFile.lastIndexOf(QLatin1Char('.')); |
|
283 licFile = licFile.left(lastDot) + QLatin1String(".lic"); |
|
284 if (QFile::exists(licFile)) |
|
285 return true; |
|
286 return false; |
|
287 } |
|
288 return licenseKey == classKey; |
|
289 } |
|
290 |
|
291 /*! |
|
292 Reimplement this function to return the name of the super class of |
|
293 \a key up to which methods and properties should be exposed by the |
|
294 ActiveX control. |
|
295 |
|
296 The default implementation interprets \a key as the class name, |
|
297 and returns the value of the \c Q_CLASSINFO() entry |
|
298 "ToSuperClass". If no such value is set the null-string is |
|
299 returned, and the functions and properties of all the super |
|
300 classes including QWidget will be exposed. |
|
301 |
|
302 To only expose the functions and properties of the class itself, |
|
303 reimplement this function to return \a key. |
|
304 */ |
|
305 QString QAxFactory::exposeToSuperClass(const QString &key) const |
|
306 { |
|
307 const QMetaObject *mo = metaObject(key); |
|
308 if (!mo) |
|
309 return QString(); |
|
310 return QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("ToSuperClass")).value()); |
|
311 } |
|
312 |
|
313 /*! |
|
314 Reimplement this function to return true if the ActiveX control \a key |
|
315 should be a top level window, e.g. a dialog. The default implementation |
|
316 returns false. |
|
317 */ |
|
318 bool QAxFactory::stayTopLevel(const QString &key) const |
|
319 { |
|
320 return false; |
|
321 } |
|
322 |
|
323 /*! |
|
324 Reimplement this function to return true if the ActiveX control |
|
325 \a key should support the standard ActiveX events |
|
326 \list |
|
327 \i Click |
|
328 \i DblClick |
|
329 \i KeyDown |
|
330 \i KeyPress |
|
331 \i KeyUp |
|
332 \i MouseDown |
|
333 \i MouseUp |
|
334 \i MouseMove |
|
335 \endlist |
|
336 |
|
337 The default implementation interprets \a key as the class name, |
|
338 and returns true if the value of the \c Q_CLASSINFO() entry |
|
339 "StockEvents" is "yes". Otherwise this function returns false. |
|
340 */ |
|
341 bool QAxFactory::hasStockEvents(const QString &key) const |
|
342 { |
|
343 const QMetaObject *mo = metaObject(key); |
|
344 if (!mo) |
|
345 return false; |
|
346 return QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("StockEvents")).value()) == QLatin1String("yes"); |
|
347 } |
|
348 |
|
349 |
|
350 extern bool qAxIsServer; |
|
351 |
|
352 /*! |
|
353 Returns true if the application has been started (by COM) as an ActiveX |
|
354 server, otherwise returns false. |
|
355 |
|
356 \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 5 |
|
357 */ |
|
358 |
|
359 bool QAxFactory::isServer() |
|
360 { |
|
361 return qAxIsServer; |
|
362 } |
|
363 |
|
364 extern wchar_t qAxModuleFilename[MAX_PATH]; |
|
365 |
|
366 /*! |
|
367 Returns the directory that contains the server binary. |
|
368 |
|
369 For out-of-process servers this is the same as |
|
370 QApplication::applicationDirPath(). For in-process servers |
|
371 that function returns the directory that contains the hosting |
|
372 application. |
|
373 */ |
|
374 QString QAxFactory::serverDirPath() |
|
375 { |
|
376 return QFileInfo(QString::fromWCharArray(qAxModuleFilename)).absolutePath(); |
|
377 } |
|
378 |
|
379 /*! |
|
380 Returns the file path of the server binary. |
|
381 |
|
382 For out-of-process servers this is the same as |
|
383 QApplication::applicationFilePath(). For in-process servers |
|
384 that function returns the file path of the hosting application. |
|
385 */ |
|
386 QString QAxFactory::serverFilePath() |
|
387 { |
|
388 return QString::fromWCharArray(qAxModuleFilename); |
|
389 } |
|
390 |
|
391 /*! |
|
392 Reimplement this function to return true if the server is |
|
393 running as a persistent service (e.g. an NT service) and should |
|
394 not terminate even when all objects provided have been released. |
|
395 |
|
396 The default implementation returns false. |
|
397 */ |
|
398 bool QAxFactory::isService() const |
|
399 { |
|
400 return false; |
|
401 } |
|
402 |
|
403 /*! |
|
404 \enum QAxFactory::ServerType |
|
405 |
|
406 This enum specifies the different types of servers that can be |
|
407 started with startServer. |
|
408 |
|
409 \value SingleInstance The server process can create only one instance of each |
|
410 exported class. COM starts a new process for each request. This is typically |
|
411 used in servers that export only one creatable class. |
|
412 \value MultipleInstances The server can create multiple instances of |
|
413 each exported class. This is the default. All instances will live in the same |
|
414 thread, and will share static resources. |
|
415 */ |
|
416 |
|
417 /*! |
|
418 \fn bool QAxFactory::startServer(ServerType type); |
|
419 |
|
420 Starts the COM server with \a type and returns true if successful, |
|
421 otherwise returns false. |
|
422 |
|
423 Calling this function if the server is already running (or for an |
|
424 in-process server) does nothing and returns true. |
|
425 |
|
426 The server is started automatically with \a type set to \c MultipleInstances |
|
427 if the server executable has been started with the \c -activex |
|
428 command line parameter. To switch to SingleInstance, call |
|
429 |
|
430 \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 6 |
|
431 |
|
432 in your own main() entry point function. |
|
433 */ |
|
434 |
|
435 /*! |
|
436 \fn bool QAxFactory::stopServer(); |
|
437 |
|
438 Stops the COM server and returns true if successful, otherwise |
|
439 returns false. |
|
440 |
|
441 Calling this function if the server is not running (or for an |
|
442 in-process server) does nothing and returns true. |
|
443 |
|
444 Stopping the server will not invalidate existing objects, but no |
|
445 new objects can be created from the existing server process. Usually |
|
446 COM will start a new server process if additional objects are requested. |
|
447 |
|
448 The server is stopped automatically when the main() function returns. |
|
449 */ |
|
450 |
|
451 class ActiveObject : public QObject |
|
452 { |
|
453 public: |
|
454 ActiveObject(QObject *parent, QAxFactory *factory); |
|
455 ~ActiveObject(); |
|
456 |
|
457 IDispatch *wrapper; |
|
458 DWORD cookie; |
|
459 }; |
|
460 |
|
461 ActiveObject::ActiveObject(QObject *parent, QAxFactory *factory) |
|
462 : QObject(parent), wrapper(0), cookie(0) |
|
463 { |
|
464 QLatin1String key(parent->metaObject()->className()); |
|
465 |
|
466 factory->createObjectWrapper(parent, &wrapper); |
|
467 if (wrapper) |
|
468 RegisterActiveObject(wrapper, QUuid(factory->classID(key)), ACTIVEOBJECT_STRONG, &cookie); |
|
469 } |
|
470 |
|
471 ActiveObject::~ActiveObject() |
|
472 { |
|
473 if (cookie) |
|
474 RevokeActiveObject(cookie, 0); |
|
475 if (wrapper) |
|
476 wrapper->Release(); |
|
477 } |
|
478 |
|
479 /*! |
|
480 Registers the QObject \a object with COM as a running object, and returns true if |
|
481 the registration succeeded, otherwise returns false. The object is unregistered |
|
482 automatically when it is destroyed. |
|
483 |
|
484 This function should only be called if the application has been started by the user |
|
485 (i.e. not by COM to respond to a request), and only for one object, usually the |
|
486 toplevel object of the application's object hierarchy. |
|
487 |
|
488 This function does nothing and returns false if the object's class info for |
|
489 "RegisterObject" is not set to "yes", or if the server is an in-process server. |
|
490 */ |
|
491 bool QAxFactory::registerActiveObject(QObject *object) |
|
492 { |
|
493 if (qstricmp(object->metaObject()->classInfo(object->metaObject()->indexOfClassInfo("RegisterObject")).value(), "yes")) |
|
494 return false; |
|
495 |
|
496 if (!QString::fromWCharArray(qAxModuleFilename).toLower().endsWith(QLatin1String(".exe"))) |
|
497 return false; |
|
498 |
|
499 ActiveObject *active = new ActiveObject(object, qAxFactory()); |
|
500 if (!active->wrapper || !active->cookie) { |
|
501 delete active; |
|
502 return false; |
|
503 } |
|
504 return true; |
|
505 } |
|
506 |
|
507 /*! |
|
508 \macro QAXFACTORY_DEFAULT(Class, ClassID, InterfaceID, EventID, LibID, AppID) |
|
509 \relates QAxFactory |
|
510 |
|
511 This macro can be used to export a single QObject subclass \a Class a this |
|
512 COM server through an implicitly declared QAxFactory implementation. |
|
513 |
|
514 This macro exports the class \a Class as a COM coclass with the CLSID \a ClassID. |
|
515 The properties and slots will be declared through a COM interface with the IID |
|
516 \a InterfaceID, and signals will be declared through a COM event interface with |
|
517 the IID \a EventID. All declarations will be in a type library with the id \a LibID, |
|
518 and if the server is an executable server then it will have the application id |
|
519 \a AppID. |
|
520 |
|
521 \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 7 |
|
522 |
|
523 \sa QAXFACTORY_EXPORT(), QAXFACTORY_BEGIN() |
|
524 */ |
|
525 |
|
526 /*! |
|
527 \macro QAXFACTORY_EXPORT(Class, LibID, AppID) |
|
528 \relates QAxFactory |
|
529 |
|
530 This macro can be used to export a QAxFactory implementation \a Class from |
|
531 a COM server. All declarations will be in a type library with the id \a LibID, |
|
532 and if the server is an executable server then it will have the application id |
|
533 \a AppID. |
|
534 |
|
535 \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 8 |
|
536 |
|
537 \sa QAXFACTORY_BEGIN() |
|
538 */ |
|
539 |
|
540 /*! |
|
541 \macro QAXFACTORY_BEGIN(IDTypeLib, IDApp) |
|
542 \relates QAxFactory |
|
543 |
|
544 This macro can be used to export multiple QObject classes through an |
|
545 implicitly declared QAxFactory implementation. All QObject classes have to |
|
546 declare the ClassID, InterfaceID and EventsID (if applicable) through the |
|
547 Q_CLASSINFO() macro. All declarations will be in a type library with the id |
|
548 \a IDTypeLib, and if the server is an executable server then it will have the |
|
549 application id \a IDApp. |
|
550 |
|
551 This macro needs to be used together with the QAXCLASS(), QAXTYPE() |
|
552 and QAXFACTORY_END() macros. |
|
553 |
|
554 \snippet doc/src/snippets/code/src_activeqt_control_qaxfactory.cpp 9 |
|
555 */ |
|
556 |
|
557 /*! |
|
558 \macro QAXCLASS(Class) |
|
559 \relates QAxFactory |
|
560 |
|
561 This macro adds a creatable COM class \a Class to the QAxFactory declared |
|
562 with the QAXFACTORY_BEGIN() macro. |
|
563 |
|
564 \sa QAXFACTORY_BEGIN(), QAXTYPE(), QAXFACTORY_END(), Q_CLASSINFO() |
|
565 */ |
|
566 |
|
567 /*! |
|
568 \macro QAXTYPE(Class) |
|
569 \relates QAxFactory |
|
570 |
|
571 This macro adds a non-creatable COM class \a Class to the QAxFactory |
|
572 declared with the QAXFACTORY_BEGIN(). The class \a Class can be used |
|
573 in APIs of other COM classes exported through QAXTYPE() or QAXCLASS(). |
|
574 |
|
575 Instances of type \a Class can only be retrieved using APIs of already |
|
576 instantiated objects. |
|
577 |
|
578 \sa QAXFACTORY_BEGIN(), QAXCLASS(), QAXFACTORY_END(), Q_CLASSINFO() |
|
579 */ |
|
580 |
|
581 /*! |
|
582 \macro QAXFACTORY_END() |
|
583 \relates QAxFactory |
|
584 |
|
585 Completes the QAxFactory declaration started with the QAXFACTORY_BEGIN() |
|
586 macro. |
|
587 |
|
588 \sa QAXFACTORY_BEGIN(), QAXCLASS(), QAXTYPE() |
|
589 */ |
|
590 |
|
591 QT_END_NAMESPACE |
|
592 #endif // QT_NO_WIN_ACTIVEQT |