Home | All Classes | Main Classes | Annotated | Grouped Classes | Functions |

# The QAxServer Module

- Introduction
- Building the library
- Using the library
  - Out-of-process vs. In-process
- Implementing Controls
  - Data Types
  - Sub-Objects
  - Property Notification
- Serving Controls
- Using the Controls
- Enhanced features
  - More Interfaces
  - Fewer methods and properties

## Introduction

The QAxServer module provides a static library implementing the functions required to turn a standard Qt binary into an ActiveX control server.

This module is part of the ActiveQt framework. (To incorporate ActiveX controls in a Qt application see the QAxContainer module.)

The module consists of three classes

- QAxFactory defines a factory for the creation of ActiveX components.
- QAxBindable provides an interface between the Qt widget and the ActiveX control.
- QAxAggregated can be subclassed to implement additional COM interfaces.

Some example implementations of ActiveX controls are provided.

## Building the library

In the `activeqt` directory (usually `QTDIR/extensions/activeqt`) enter the `control` subdirectory and run `qmake` to generate the makefile, and use the make tool (`nmake` for VC++, `make` for Borland) to build the library. The library `qaxserver.lib` will be linked into `QTDIR/lib`.

## Using the library

To turn a standard Qt application into an ActiveX server using the QAxServer library you must add `activeqt` as a CONFIG setting in your `.pro` file.

An out-of-process executable server is generated from a `.pro` file like this:

        TEMPLATE = app
        CONFIG  += qt activeqt

        RC_FILE  = qaxserver.rc
        ...

To build an in-process server, use a `.pro` file like this:

        TEMPLATE = lib
        CONFIG  += qt activeqt dll

        DEF_FILE = qaxserver.def
        RC_FILE  = qaxserver.rc
        ...

The files `qaxserver.rc` and `qaxserver.def` are part of the framework and can be used from their usual location (specify a path in the `.pro` file), or copied into the project directory. You should not modify these files.

The `activeqt` configuration will cause the `qmake` tool to add the required build steps to the build system:

- link the binary against `qaxserver.lib`
- generate an interface definition and link the type library into the binary
- register the server

See the QAxServer FAQ for a list of common problems when building the ActiveX server.

### Out-of-process vs. In-process

Whether your ActiveX server should run as a stand-alone executable or as a shared library in the client process depends mainly on the type of controls you want to provide in the server.

An executable server has the advantage of being able to run as a stand-alone application, but adds considerable overhead to the communication between the ActiveX client and the control. If the control has a programming error only the server process running the control will crash, and the client application will probably continue to run.

An in-process server is usually smaller and has faster startup time. The communication between client and server is done directly through virtual function calls and does not introduce the overhead required for remote procedure calls. But if the server crashes the client application is likely to crash as well.

Both server types can use Qt either as a shared library, or statically linked into the server binary.

## Implementing Controls

To implement an ActiveX control with Qt, create a subclass of QWidget or any existing QWidget subclass:

        #include <qwidget.h>

        class MyActiveX : public QWidget
        {
            Q_OBJECT

The Q_OBJECT macro is required to provide the meta object information about the widget to the ActiveQt framework. Use the `Q_PROPERTY` macro to declare properties for the ActiveX control:

            Q_PROPERTY( int value READ value WRITE setValue )

Declare a standard QWidget constructor taking a parent widget and a name, and functions, signals and slots like any normal QWidget. (1)

        public:
            MyActiveX( QWidget *parent = 0, const char *name = 0 )
            ...

            int value() const;

        public slots:
            void setValue( int );
            ...

        signals:
            void valueChange( int );
            ...

        };

The ActiveQt framework will expose properties and public slots as ActiveX properties and methods, and signals as ActiveX events, and convert between the Qt data types and the equivalent COM data types.

### Data Types

The Qt data types that are supported for properties are:

Qt data type | COM property
--- | ---
bool | VARIANT_BOOL
QString | BSTR
QCString | BSTR
int | int
uint | unsigned int
double | double
QColor | OLE_COLOR
QDate | DATE
QDateTime | DATE
QFont | IFontDisp*
QPixmap | IPictureDisp* (2)
QValueList | SAFEARRAY(VARIANT)
QByteArray | SAFEARRAY(BYTE)

The Qt data types that are supported for parameters in signals and slots are:

Qt data type | COM parameter
--- | ---
bool | [in] VARIANT_BOOL
bool& | [in, out] VARIANT_BOOL*
QString, const QString& | [in] BSTR
QString& | [in, out] BSTR*
QCString, const QCString& | [in] BSTR
QString& | [in, out] BSTR*
int | [in] int
int& | [in,out] int
uint | [in] unsigned int
uint& | [in, out] unsigned int*
double | [in] double
double& | [in, out] double*
QColor, const QColor& | [in] OLE_COLOR
QColor& | [in, out] OLE_COLOR*
QDate, const QDate& | [in] DATE
QDate& | [in, out] DATE*
QDateTime, const QDateTime& | [in] DATE
QDateTime& | [in, out] DATE*
QFont, const QFont& | [in] IFontDisp*
QFont& | [in, out] IFontDisp**
QPixmap, const QPixmap& | [in] IPictureDisp*
QPixmap& | [in, out] IPictureDisp**
QValueList<QVariant>, const QValueList<QVariant>& | [in] SAFEARRAY(VARIANT)
QValueList<QVariant>& | [in, out] SAFEARRAY(VARIANT)*
QByteArray, const QByteArray& | [in] SAFEARRAY(BYTE)
QByteArray& | [in, out] SAFEARRAY(BYTE)*
QObject* | [in] IDispatch*

Also supported are exported enums and sets (see Q_ENUMS and Q_SETS). The in-parameter types are also supported as return values.

Properties and signals/slots that have parameters using any other data types are ignored by the QActiveX framework.

### Sub-Objects

COM objects can have multiple sub-objects that can represent a sub element of the COM object. A COM object representing a multi-document spread sheet application can for example provide one sub-object for each spread sheet.

Any QObject subclass can be used as the type for a sub object in ActiveX. The QAxFactory implementation (see below) needs to return the classname of the sub type as one key in the featureList() implementation, as well as the IDs for the COM class, the interface and event interface of that type. Then the type can be used as e.g. the return value or paramter of a slot.

### Property Notification

To make the properties bindable for the ActiveX client, use multiple inheritance from the QAxBindable class:

        #include <qwidget.h>
        #include <qaxbindable.h>

        class MyActiveX : public QWidget, public QAxBindable
        {
            Q_OBJECT

When implementing the property write functions, use the QAxBindable class's requestPropertyChange() and propertyChanged() functions to allow ActiveX clients to bind to the control properties. (3)

## Serving Controls

To make an ActiveX control available to the COM system it must be registered in the system registry using five unique identifiers. These identifiers are provided by tools like `guidgen` or `uuidgen`. The registration information allows COM to localize the binary providing a requested ActiveX control, marshall remote procedure calls to the control and read type information about the methods and properties exposed by the control.

To create the ActiveX control when the client asks for it the server must export an implementation of a QAxFactory. Use the default factory when the server provides only a single ActiveX control, and implement a subclass of QAxFactory to provide multiple ActiveX controls. The default factory is available through a macro that takes the identifiers COM requires to locate the ActiveX control on the target system:

        QAXFACTORY_DEFAULT ( MyActiveX,
                    "{ad90301a-849e-4e8b-9a91-0a6dc5f6461f}",
                    "{87a5b65e-7fa9-4dc6-a176-47295988dcbd}",
                    "{a6130ae9-8327-47ec-815b-d0b45a0d6e5e}",
                    "{26c4e136-4e23-4347-af37-faf933b027e9}",
                    "{a8f21901-7ff7-4f6a-b939-789620c03d83}" )

The QAxFactory class documentation explains how to use this macro, and how to implement and use custom factories.

For out-of-process executable servers, implement a main() function, instantiate a QApplication object, and enter the event loop just like any normal Qt application. By default the application will start as a standard Qt application, but if you pass `-activex` on the command line it will start as an ActiveX server. Use QAxFactory::isServer() to create and run a standard application interface, or to prevent a stand-alone execution:

        #include <qapplication.h>
        #include <qaxfactory.h>

        int main( int argc, char **argv )
        {
            QApplication app( argc, argv );
            if ( !QAxFactory::isServer() ) {
                // create and show main window...
            }
            return app.exec();
        }

In-process servers must also implement `main()`; but it is never called so a dummy implementation is sufficient.

        int main( int , char ** )
        {
            return 0;
        }

To build the ActiveX server executable run qmake to generate the makefile, and use your compiler's make tool as for any other Qt application. The make process will also register the controls in the system registry by calling the resulting executable with the `-regserver` command line option. See the Typical build errors list for information on problems that can occur when building the ActiveQt server executable.

If the ActiveX server is an executable, the following command line options are supported:

Option | Result
--- | ---
`-regserver` | Registers the server in the system registry
`-unregserver` | Unregisters the server from the system registry
`-activex` | Starts the application as an ActiveX server
`-dumpidl <file>` | Writes the server's IDL to the specified file

In-process servers can be registered using the `regsvr32` tool available on all Windows systems.

## Using the Controls

To use the ActiveX controls, e.g. to embed them in a web page, use the `<object>` HTML tag.

        <object ID="MyActiveX1" CLASSID="CLSID:ad90301a-849e-4e8b-9a91-0a6dc5f6461f">
           ...
        <\object>

To initialize the control's properties, use

        <object ID=...>
            <param name="name" value="value">
        <\object>

If the web browser supports scripting use JavaScript, VBScript and forms to script the control. The examples include demonstration HTML pages for the example controls.

## Enhanced features

### More Interfaces

The ActiveX control provide by ActiveQt servers supports a minimal set of COM interfaces to implement the OLE specifications. When the ActiveX class inherits from the QAxBindable class it can also implement additional COM interfaces.

Create a new subclass of QAxAggregated and use multiple inheritance to subclass additional COM interface classes.

        class AxImpl : public QAxAggregated, public ISomeCOMInterface
        {
        public:
            AxImpl() {}

            long queryInterface( const QUuid &iid, void **iface )
            {
                *iface = 0;
                if ( iid == IID_ISomeCOMInterface )
                    *iface = (ISomeCOMInterface*)this;
                else
                    return E_NOINTERFACE;

                AddRef();
                return S_OK;
            }

            // IUnknown
            QAXAGG_IUNKNOWN

            // ISomeCOMInterface
            ...
        }

Reimplement the `queryInterface()` function to support the additional COM interfaces.

        long AxImpl::queryInterface( const QUuid &iid, void **iface )
        {
            *iface = 0;
            if ( iid == IID_ISomeCOMInterface )
                *iface = (ISomeCOMInterface*)this;
            else
                return E_NOINTERFACE;

            AddRef();
            return S_OK;
        }

Since `ISomeCOMInterface` is a subclass of `IUnknown` you will have to implement the `QueryInterface`, `AddRef` and `Release` functions. Use the `QAXAGG_IUNKNOWN` macro in your class definition to do that. If you implement the IUnknown functions manually, delegate the calls to the interface pointer returned by the controllingUnknown() function, e.g.

        HRESULT AxImpl::QueryInterface( REFIID iid, void **iface )
        {
            return controllingUnknown()->QueryInterface( iid, iface );
        }

Do not support the `IUnknown` interface itself in your `queryInterface()` implementation.

Implement the methods of the COM interfaces. If you need to make calls to the QWidget implementing the ActiveX control, use QAxAggregated::widget().

In your QAxBindable subclass, implement `createAggregate()` to return a new object of the QAxAggregated subclass.

        class MyActiveX : public QWidget,
                          public QAxBindable
        {
        	Q_OBJECT
        public:
            MyActiveX( QWidget *parent, const char *name = 0 );

            QAxAggregated *createAggregate()
            {
                return new AxImpl();
            }

        };

### Fewer methods and properties

By default all ActiveX controls expose not only their own methods and properties to ActiveX clients, but also those of all super classes, including QWidget.

This can be controlled by reimplementing QAxFactory's exposeToSuperClass() function. Reimplement the function to return the last (furthest up the inheritance hierarchy) super class that should be exposed:

        QString MyFactory::exposeToSuperClass( const QString &key ) const
        {
            if ( key == "SmallActiveX" )
                return key;
            return QAxFactory::exposeToSuperClass( key );
        }

The SmallActiveX control will only expose its own functions and properties to clients, while all other ActiveX controls provided by this factory will expose their own functions and properties and also those of all their super classes including QWidget. The SmallActiveX class can of course propagate some of the QWidget functions and properties into its own interface.

1. If a standard constructor is not present the compiler will issue an error "no overloaded function takes 2 parameters" when using the default factory through the QAXFACTORY_DEFAULT macro. If you cannot provide a standard constructor you must implement a QAxFactory custom factory and call the constructor you have in your implementation of QAxFactory::create. Back...
2. COM cannot marshal IPictureDisp accross process boundaries, so QPixmap properties cannot be called for out-of-process servers. You can however marshal the image data via e.g. temporary files. See the Microsoft KB article Q150034 for more information. Back...
3. This is not required, but gives the client more control over the ActiveX control. Back...