QtでActiveXサーバーを構築する

QAxServer モジュールはActiveQtフレームワークの一部です。つのクラスから構成されています:

  • QAxFactory COM オブジェクトを作成するためのファクトリーを定義します。
  • QAxBindable Qt ウィジェットと COM オブジェクト間のインターフェースを提供します。
  • QAxAggregated COM インタフェースを追加実装するためにサブクラス化することができます。

ActiveX コントロールと COM オブジェクトの実装例がいくつか提供されています。

ライブラリの使用

QAxServer ライブラリを使用して標準 Qt アプリケーションを COM サーバーにするには、.pro ファイルの QT 変数にaxserver を追加する必要があります。

アウトオブプロセスの実行可能サーバーは、このように.pro ファイルから生成されます:

TEMPLATE = app
QT  += axserver

RC_FILE  = qaxserver.rc
...

プロセス内サーバーを構築するには、.pro ファイルを次のように使用します:

TEMPLATE = lib
QT += axserver
CONFIG  += dll

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

qaxserver.rcqaxserver.def ファイルはフレームワークの一部であり、通常の場所(.pro ファイルでパスを指定)から使用することも、プロジェクト・ディレクトリにコピーすることもできます。例えば、バージョン情報を追加したり、異なるツールボックスのアイコンを指定したりできます。

axserver モジュールを使用すると、qmake ツールが必要なビルド・ステップをビルド・システムに追加します:

  • の代わりにqaxserver.lib に対してバイナリをリンクする。qtmain.lib
  • idcツールを呼び出して COM サーバー用の IDL ファイルを生成する。
  • MIDL ツール(コンパイラのインストールの一部)を使用して IDL をタイプライブラリにコンパイルする。
  • 生成されたタイプライブラリをバイナリリソースとしてサーバーバイナリにアタッチする(この場合もidcツールを使用)。
  • サーバーを登録します。このステップには管理者権限が必要な場合があり、qaxserver_no_register の設定を行うことで省略することができます。

後処理のステップをスキップするには、qaxserver_no_postlink の設定も行ってください。

さらに、VERSION 変数を使ってバージョン番号を指定することもできます。

TEMPLATE = lib
VERSION = 2.5
...

指定されたバージョン番号は、登録時にタイプ・ライブラリとサーバーのバージョンとして使用される。

アウトオブプロセスとインプロセス

COM サーバをスタンドアロンの実行ファイルとして実行するか、クライアントプロセスの共有ライブラリとして実行するかは、主にサーバで提供したい COM オブジェクトの種類に依存します。

実行可能なサーバーは、スタンドアロンのアプリケーションとして実行できるという利点がありますが、COM クライアントと COM オブジェクト間の通信にかなりのオーバーヘッドが追加されます。コントロールにプログラミング・エラーが発生した場合、コントロールを実行しているサーバー・プロセスのみがクラッシュし、クライアント・アプリケーションはおそらく実行され続けます。すべての COM クライアントが実行可能サーバーをサポートしているわけではありません。

インプロセスサーバーは通常、サイズが小さく、起動時間が速い。クライアントとサーバー間の通信は、仮想関数呼び出しを通じて直接行われるため、リモート・プロシージャ呼び出しに必要なオーバーヘッドが発生しません。しかし、サーバーがクラッシュした場合、クライアント・アプリケーションもクラッシュする可能性が高く、インプロセス・サーバーではすべての機能が利用できるわけではありません(COMのrunning-object-tableへの登録など)。

どちらのタイプのサーバーも、Qt を共有ライブラリとして使用することも、サーバーバイナリに静的にリンクすることもできます。

ポストビルドステップでの典型的なエラー

ActiveQt 固有の後処理ステップを動作させるためには、サーバーはいくつかの要件を満たす必要があります:

  • 公開されるすべてのコントロールは、QApplication インスタンス以外何も存在しない状態で作成できます。
  • サーバーの初期リンクには、一時的なタイプ ライブラリ リソースが含まれます。
  • サーバーを実行するために必要なすべての依存関係がシステム・パス(または呼び出し元の環境で使用されているパス)にあること。Visual Studioには、ツール|オプション|ディレクトリ・ダイアログにリストされている独自の環境変数セットがあることに注意してください。

これらの要件が満たされていない場合、次のようなエラーが発生する可能性があります:

サーバ実行ファイルがクラッシュする

IDLを生成するには、ActiveXコントロールとして公開されているウィジェットをインスタンス化する必要があります(コンストラクタが呼び出されます)。この時点では、QApplication オブジェクト以外は存在しません。ウィジェットのコンストラクタは、生成される他のオブジェクトに依存してはいけません。例えば、NULLポインタをチェックする必要があります。

サーバーをデバッグするには、-dumpidl outputfileで実行し、クラッシュする場所をチェックしてください。

コントロールのどの関数も呼び出されないことに注意してください。

サーバー実行ファイルが有効なWin32アプリケーションではない

タイプ・ライブラリをアタッチすると、サーバーのバイナリが破損します。これはWindowsのバグで、リリース・ビルドでのみ発生します。

最初のリンクステップでは、ダミーのタイプ・ライブラリを実行ファイルにリンクしなければならない。例で示したように、タイプ・ライブラリーを含むリソース・ファイルをプロジェクトに追加してください。

"DLLが見つかりません"

ビルド・システムは、インターフェース定義を生成し、サーバーを登録するために、サーバーの実行ファイルを実行する必要があります。サーバーがリンクするダイナミック・リンク・ライブラリーがパス内にない場合、これは失敗する可能性があります(例えば、Visual Studio は "Directories" オプションで指定された環境設定を使用してサーバーを呼び出します)。サーバーが必要とするすべての DLL とプラグインが、エラーメッセージボックスに表示されるパスにリストされているディレクトリにあることを確認してください(Windows Deployment Tool も参照してください)。

「ファイルを開けません

最後のクライアントがActiveXサーバーの使用を停止したときに、ActiveXサーバーを正しくシャットダウンできませんでした。通常、アプリケーションが終了するまで約2秒かかりますが、タスクマネージャを使用してプロセスを強制終了する必要がある場合があります(クライアントがコントロールを正しく解放しない場合など)。

コントロールがインスタンス化できない

この場合、サーバーを Administrator として登録するとよいでしょう。

コントロールの実装

Qt で COM オブジェクトを実装するには、QObject または既存のQObject のサブクラスを作成します。QWidget のサブクラスの場合、COM オブジェクトは ActiveX コントロールになります。

#include <QWidget>

class MyActiveX : public QWidget
{
    Q_OBJECT

Q_OBJECT マクロは、ウィジェットに関するメタ・オブジェクト情報を ActiveQt フレームワークに提供するために必要です。

Q_CLASSINFO("ClassID", "{1D9928BD-4453-4bdd-903D-E525ED17FDE5}")
Q_CLASSINFO("InterfaceID", "{99F6860E-2C5A-42ec-87F2-43396F4BE389}")
Q_CLASSINFO("EventsID", "{0A3E9F27-E4F1-45bb-9E47-63099BCCD0E3}")

COM オブジェクトの COM 識別子を指定するには、Q_CLASSINFO() マクロを使用します。ClassIDInterfaceID は必須で、EventsID はオブジェクトにシグナルがある場合にのみ必要です。これらの識別子を生成するには、uuidgenguidgen などのシステム・ツールを使用します。

詳細は「クラス情報とチューニング」を参照してください。

Q_PROPERTY(int value READ value WRITE setValue)

Q_PROPERTY() マクロを使用して、ActiveX コントロールのプロパティを宣言します。

親オブジェクトを取る標準のコンストラクタと、QObject のサブクラスのような関数、シグナル、スロットを宣言します。

public:
    MyActiveX(QWidget *parent = 0)
    ...

    int value() const;

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

signals:
    void valueChange(int v);
    ...

};

ActiveQtフレームワークは、プロパティとパブリック・スロットをActiveXプロパティとメソッドとして、シグナルをActiveXイベントとして公開し、Qtデータ型と同等のCOMデータ型の間で変換します。

データ型

プロパティでサポートされている Qt データ型は以下の通りです:

Qt データ型COM プロパティ
ブールVARIANT_BOOL
QStringBSTR
intint
uint符号なしint
doubledouble
qlonglongCY
qulonglongCY
QColorOLE_COLOR
QDate日付
QDateTime日付
QTime日付
QFontIFontDisp*(フォントディスプ
QPixmapIPictureDisp*
QVariantバリアント
QVariantList ( < >と同じ)QListQVariantsafearray(バリアント)
QStringListセーフアレイ(bstr)
QByteArraysafearray(バイト)
QRectユーザー定義型
QSizeユーザー定義型
QPointユーザー定義型

シグナルやスロットのパラメータとしてサポートされているQtのデータ型は以下の通りです:

Qt データ型COMパラメータ
ブール[in] VARIANT_BOOL
bool&[in, out] VARIANT_BOOL* , const & bool*.
QStringconstQString&[in] BSTR
QString&[in, out] BSTR*
QString&[in, out] BSTR*
int[int
int&[in,out] int
uint[符号なしint
uint&[in, out] 符号なし int*
double[in] double
double&[in, out] double*
QColorconstQColor&[in] OLE_COLOR
QColor&[in, out] OLE_COLOR*.
QDate, constQDate&[in] DATE
QDate&[in, out] DATE*
QDateTime, constQDateTime&[in] DATE
QDateTime&[in, out] DATE*
QFont, constQFont&[in] IFontDisp*
QFont&[in, out] IFontDisp**
QPixmap, constQPixmap&[in] IPictureDisp*
QPixmap&[in, out] IPictureDisp**.
QList<QVariant>, constQList<QVariant>&, const 。[in] SAFEARRAY(VARIANT)
QList<QVariantin, out] SAFEARRAY(VARIANT)* , const & [in, out] IPictureDisp** < >.
QStringList, constQStringList&[in] SAFEARRAY(BSTR)
QStringList&[in, out] SAFEARRAY(BSTR)*.
QByteArray, constQByteArray&[in] SAFEARRAY(BYTE)
QByteArray&[in, out] SAFEARRAY(BYTE)* , const & [in] SAFEARRAY(BYTE)*
QObject*[in] IDispatch*
QRect&[in, out] structQRect (ユーザー定義)
QSize&[in, out] structQSize (ユーザー定義)
QPoint&[in, out] structQPoint (ユーザー定義)

また、エクスポートされた列挙型とフラグもサポートされている(Q_ENUM() とQ_FLAG() を参照)。パラメータ内の型は、戻り値としてもサポートされています。

その他のデータ型を使用するパラメータを持つプロパティやシグナル/スロットは、ActiveQt フレームワークによって無視されます。

サブオブジェクト

COMオブジェクトは、COMオブジェクトのサブ要素を表す複数のサブオブジェクトを持つことができます。例えば、複数ドキュメントのスプレッド・シート・アプリケーションを表す COM オブジェクトは、各スプレッド・シートに 1 つのサブ・オブジェクトを提供できます。

QAxFactory で既知である限り、QObject のサブクラスを ActiveX のサブオブジェクトの型として使用することができます。その後、その型をプロパティで使用したり、戻り値の型やスロットのパラメータとして使用することができます。

プロパティの通知

ActiveX クライアントでプロパティをバインド可能にするには、QAxBindable クラスからの多重継承を使用します:

#include <QAxBindable>
#include <QWidget>

class MyActiveX : public QWidget, public QAxBindable
{
    Q_OBJECT

プロパティ書き込み関数を実装する場合は、QAxBindable クラスの requestPropertyChange() 関数と propertyChanged() 関数を使用して、ActiveX クライアントがコントロールのプロパティにバインドできるようにします。

コントロールのサービング

COM サーバを COM システムで使用できるようにするには、5 つの一意な識別子を使用してシステム・レジストリに登録する必要があります。これらの識別子は、guidgenuuidgen などのツールによって提供されます。登録情報によって、COM は要求された ActiveX コントロールを提供するバイナリをローカライズし、コントロールへのリモートプロシージャコールをマーシャルし、コントロールが公開するメソッドとプロパティに関する型情報を読み取ることができます。

クライアントからの要求に応じて COM オブジェクトを作成するには、サーバーがQAxFactory の実装をエクスポートする必要があります。これを行う最も簡単な方法は、一連のマクロを使用することです:

QAXFACTORY_BEGIN("{ad90301a-849e-4e8b-9a91-0a6dc5f6461f}",
                 "{a8f21901-7ff7-4f6a-b939-789620c03d83}")
    QAXCLASS(MyWidget)
    QAXCLASS(MyWidget2)
    QAXTYPE(MySubType)
QAXFACTORY_END()

これは、MyWidgetMyWidget2 を COM クライアントが作成できる COM オブジェクトとしてエクスポートし、MySubTypeMyWidgetMyWidget2 のプロパティとパラメータで使用できる型として登録します。

QAxFactory class documentation では、このマクロの使用方法と、カスタム・ファクトリの実装および使用方法について説明します。

アウトオブプロセスの実行可能なサーバでは、通常の Qt アプリケーションと同様に、QApplication オブジェクトをインスタンス化し、イベントループに入るための main() 関数を実装することができます。デフォルトではアプリケーションは標準 Qt アプリケーションとして起動しますが、コマンドラインで-activex を渡すと ActiveX サーバーとして起動します。QAxFactory::isServer() を使用すると、標準のアプリケーション・インターフェイスを作成して実行したり、スタンドアロンでの実行を防ぐことができます:

#include <QApplication>
#include <QAxFactory>

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

ただし、ActiveQt はメイン関数のデフォルト実装を提供しているので、これは必要ありません。デフォルトの実装では、QAxFactory::startServer ()を呼び出し、QApplication インスタンスを作成して exec()を呼び出します。

ActiveX サーバーの実行ファイルをビルドするには、qmake を実行して makefile を生成し、他の Qt アプリケーションと同様にコンパイラの make ツールを使用してください。makeプロセスでは、-regserver コマンドラインオプションを指定して実行ファイルを呼び出すことで、システムレジストリにコントロールを登録することもできます。

ActiveX サーバーが実行可能ファイルの場合、以下のコマンドラインオプションがサポートされています:

オプション結果
-regserverシステム・レジストリにサーバーを登録する
-regserverperuser現在のユーザーのシステムレジストリにサーバーを登録します(5.14 以降)。
-unregserverシステムレジストリからのサーバーの登録解除
-unregserverperuser現在のユーザーのシステムレジストリからサーバーの登録を解除(5.14以降)
-activexアプリケーションをActiveXサーバーとして起動
-dumpidl <file> -version x.yサーバーのIDLを指定されたファイルに書き込みます。タイプライブラリのバージョンはx.yになります。

インプロセス・サーバーは、すべてのWindowsシステムで利用可能なregsvr32 ツールを使用して登録できます。

典型的なコンパイル時の問題

以下に挙げるコンパイラ/リンカ・エラーは、Microsoft Visual C++ 6.0コンパイラのエラーに基づくものです。

"オーバーロードされた関数は2つのパラメータを取らない"

このエラーがQAXCLASS() または QAXFACTORY_DEFAULT() マクロを使用するコードで発生する場合、ウィジェット・クラスにはデフォルト・ファクトリで使用できるコンストラクタがありません。標準のウィジェットコンストラクタを追加するか、コンストラクタを必要としないカスタムファクトリを実装してください。

QAXFACTORY_EXPORT() マクロを使用するコードでエラーが発生する場合、QAxFactory サブクラスに適切なコンストラクタがありません。ファクトリクラスに

MyFactory(const QUuid &, const QUuid &);

のようなパブリッククラスのコンストラクタを用意してください。

"構文エラー: 番号の接尾辞が正しくありません"

一意の識別子が、QAXFACTORY_EXPORT()、QAXFACTORY_BEGIN()、または QAXFACTORY_DEFAULT() マクロに文字列として渡されていません。

「未解決の外部シンボル _ucm_instantiate"

サーバはQAxFactory の実装をエクスポートしません。プロジェクトの実装ファイルの 1 つでQAXFACTORY_EXPORT() マクロを使用してファクトリをインスタンス化してエクスポートするか、QAXCLASS() または QAXFACTORY_DEFAULT() マクロを使用してデフォルトのファクトリを使用します。

"_ucm_initialize already defined in ..."

サーバがQAxFactory の複数の実装をエクスポートしているか、同じ実装を 2 回エクスポートしています。既定のファクトリを使用する場合は、QAXFACTORY_BEGIN() または QAXFACTORY_DEFAULT() マクロをプロジェクト内で 1 回だけ使用する必要があります。サーバーが複数の ActiveX コントロールを提供する場合は、カスタムのQAxFactory 実装とQAXFACTORY_EXPORT() マクロを使用してください。

QAxServer バイナリの配布

Qt で記述された ActiveX サーバーは、Qt を共有ライブラリとして使用するか、Qt をバイナリに静的にリンクすることができます。どちらの方法でも、かなり大きなパッケージが作成されます(サーバーバイナリ自体が大きくなるか、Qt DLLを配布する必要があります)。

スタンドアロンサーバーのインストール

ActiveX サーバーがスタンドアロン・アプリケーションとしても動作する場合は、ターゲット・システムに実行ファイルをインストールした後、-regserver コマンド・ライン・パラメーターを指定してサーバー実行ファイルを実行してください。その後、サーバーが提供するコントロールをActiveXクライアントが使用できるようになります。

プロセス内サーバーのインストール

ActiveXサーバーがインストール・パッケージの一部である場合、Microsoftが提供するregsvr32 ツールを使用して、ターゲット・システムにコントロールを登録します。このツールがない場合は、インストーラプロセスに DLL をロードし、DllRegisterServer シンボルを解決して関数を呼び出します:

HMODULE dll = LoadLibrary("myserver.dll");
typedef HRESULT(__stdcall *DllRegisterServerProc)();
DllRegisterServerProc DllRegisterServer =
    (DllRegisterServerProc)GetProcAddress(dll, "DllRegisterServer");

HRESULT res = E_FAIL;
if (DllRegisterServer)
    res = DllRegisterServer();
if (res != S_OK)
    // error handling

インターネット上でのサーバーの配布

ウェブ・ページでサーバーのコントロールを使いたい場合、ページを表示するブラウザがサーバーを利用できるようにする必要があり、ページ内でサーバー・パッケージの場所を指定する必要があります。

サーバーの場所を指定するには、ウェブサイトのOBJECTタグでCODEBASE属性を使います。この値は、サーバー・ファイルそのもの、サーバーが必要とする他のファイル(Qt DLLなど)をリストしたINFファイル、または圧縮されたCABアーカイブを指すことができます。

INFファイルやCABファイルについては、ActiveXやCOMプログラミングに関するほとんどすべての本や、MSDNライブラリ、その他さまざまなオンラインリソースに記載されています。この例には、CAB アーカイブの構築に使用できる INF ファイルが含まれています:

[version]
    signature="$CHICAGO$"
    AdvancedINF=2.0
 [Add.Code]
    simpleax.exe=simpleax.exe
 [simpleax.exe]
    file-win32-x86=thiscab
    clsid={DF16845C-92CD-4AAB-A982-EB9840E74669}
    RegisterServer=yes

MicrosoftのCABARCツールは、CABアーカイブを簡単に生成できます:

cabarc N simpleax.cab simpleax.exe simple.inf

INFファイルはQtのスタティックビルドを想定しているため、INFファイルには他のDLLへの依存関係は記載されていません。DLLに依存するActiveXサーバーを配布するには、依存関係を追加し、アーカイブにライブラリファイルを提供する必要があります。

コントロールの使用

ActiveX コントロールを使用するには、<object> HTML タグを使用します。

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

コントロールのプロパティを初期化するには、次のようにします。

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

Web ブラウザがスクリプトをサポートしている場合は、JavaScript、VBScript、フォームを使用してコントロールをスクリプト化します。ActiveQt Examplesには、サンプル・コントロールのデモ HTML ページが含まれています。

サポートされているActiveXクライアントとサポートされていないActiveXクライアント

以下は、ActiveXコントロールとクライアント・アプリケーションに関する私たち自身の経験に基づくもので、決して完全なものではありません。

サポートされているクライアント

これらの標準アプリケーションは、ActiveQtで開発されたActiveXコントロールで動作します。クライアントによっては、インプロセス・コントロールのみをサポートしているものもあります。

  • インターネットエクスプローラ
  • Microsoft ActiveX コントロールテストコンテナ
  • Microsoft Visual Studio 6.0
  • Microsoft Visual Studio.NET/2003
  • Microsoft Visual Basic 6.0
  • MFCおよびATLベースのコンテナ
  • Sybase PowerBuilder
  • ActiveQtベースのコンテナ

Microsoft Officeアプリケーションはサポートされていますが、コントロールを「挿入可能」オブジェクトとして登録する必要があります。QAxFactory::registerClass を再実装して COM クラスにこの属性を追加するか、Q_CLASSINFO マクロを使用してクラスの「Insertable」クラス情報を「yes」に設定します。

サポートされていないクライアント

以下のクライアントアプリケーションでは、ActiveQt ベースの COM オブジェクトを動作させることができません。

  • Borland C++ Builder(バージョン 5 および 6)
  • Borland Delphi

典型的なランタイムエラー

サーバーが応答しない

システムがサーバーを起動できない場合(タスクマネージャーでサーバーがプロセスを実行しているかどうかを確認してください)、サーバーが依存する DLL がシステムパスから欠落していないことを確認してください(Qt DLL など)。依存関係ウォーカーを使用して、サーバーバイナリのすべての依存関係を表示します。

サーバーが実行されている(タスクマネージャにプロセスが表示されているなど)場合は、サーバーのデバッグについて、次のセクションを参照してください。

オブジェクトが作成できない

サーバーがビルドされ、ビルドプロセス中に正しく登録されたにもかかわらず、OLE/COM Object Viewer アプリケーションなどでオブジェクトを開始できない場合は、サーバーが依存する DLL がシステムパスから欠落していないか確認してください(Qt DLL など)。依存関係ウォーカーを使用して、サーバー・バイナリのすべての依存関係を表示します。

サーバーが実行される場合は、サーバーのデバッグに関する情報について、次のセクションを参照してください。

COM サーバーのアンロードとリロード時にクラッシュする

ActiveQt COM サーバーが Qt Base 以外の Qt モジュールを使用している場合、アウトオブプロセス COM サーバーとして COM サーバーをアクティブにする必要があります。Qt Quick のようなモジュールを含むインプロセス COM サーバーをアクティブにしようとすると、COM サーバーをアンロードした後にクラッシュする可能性があります。

発信 COM 呼び出し時のクラッシュまたは予期しない動作

アウトオブプロセスCOMサーバーは、クライアントへの発信を実行している間、メッセージキューを処理していることに注意してください。クライアントが同時にサーバーを呼び出している場合、予期しない動作やクラッシュにつながる可能性があります。このような状況では、発信呼び出しが戻る前に、着信呼び出しがサーバーで実行されます。特に、コントロールがクライアントにコールバックしている間にクライアントがActiveXコントロールを閉じると、クラッシュにつながる可能性があります。このようなリエントランシー問題は、メッセージ・フィルタ(IMessageFilterとCoRegisterMessageFilter)を使用することで軽減できます。

ランタイム・エラーのデバッグ

Visual Studio* でインプロセス・サーバーをデバッグするには、サーバー・プロジェクトをアク ティブ・プロジェクトに設定し、プロジェクトの設定でクライアントの「デバッグ・セッション用実 行ファイル」を指定します(例:ActiveX Test Container を使用)。コードにブレークポイントを設定したり、デバッグバージョンをインストールした場合は、ActiveQt や Qt のコードに踏み込んだりすることができます。

実行可能なサーバーをデバッグするには、デバッガーでアプリケーションを実行し、コマンドラインパラメーター-activex で開始します。次にクライアントを起動し、ActiveX コントロールのインスタンスを作成します。COMは、次にActiveXコントロールを作成しようとするクライアントに既存のプロセスを使用します。

クラス情報とチューニング

各 COM クラスの属性を提供するには、Qt のメタ・オブジェクト・システムの一部であるQ_CLASSINFO マクロを使用します。

キー値の意味
バージョンクラスのバージョン (1.0 がデフォルト)
説明クラスを説明する文字列。
クラスIDクラスID。指定されていない場合は、QAxFactory::classID を再実装する必要があります。
InterfaceIDインターフェース ID。指定されていない場合は、QAxFactory::interfaceID を再実装する必要があります。
イベントIDイベント・インターフェースID。指定されていない場合、COM イベントとして公開されるシグナルはありません。
DefaultProperty指定されたプロパティは、このクラスのデフォルト・プロパティを表します。例:プッシュ・ボタンのデフォルト・プロパティは "text"。
デフォルト・シグナル指定されたシグナルは、このクラスのデフォルト・シグナルを表します。例えば、プッシュ・ボタンのデフォルト・シグナルは "clicked" です。
ライセンス・キーオブジェクトの作成には、指定されたライセンス・キーが必要です。ライセンス・マシンを必要とする場合は、キーを空にできます。既定では、クラスはライセンスされません。以下のセクションも参照してください。
ストック・イベント値が "yes" の場合、オブジェクトはストック・イベントを公開します。QAxFactory::hasStockEvents() を参照してください。
ToSuperClassオブジェクトは、"value" に含まれるクラス名までのすべてのスーパークラスの機能を公開します。QAxFactory::exposeToSuperClass() を参照。
挿入可能値が "yes" の場合、クラスは "Insertable" として登録され、OLE 2 コンテナ (Microsoft Office など) にリストされます。この属性はデフォルトでは設定されていません。
集約可能値が "no" の場合、クラスは集約をサポートしません。デフォルトでは集約がサポートされています。
作成可能値が "no "の場合、そのクラスはクライアントから作成できず、別のクラスの API を通してのみ利用可能です (つまり、そのクラスはサブタイプです)。
オブジェクトの登録値が "yes "の場合、このクラスのオブジェクトは OLE に登録され、実行中のオブジェクト・テーブルからアクセス可能になります(つまり、クライアントはこのクラスの既に実行中のインスタンスに接続できます)。この属性は、アウトオブプロセスサーバでのみサポートされます。
MIMEオブジェクトは、値で指定された形式のデータやファイルを扱うことができます。値は、mime:extension:description の形式を持ちます。複数のフォーマットはセミコロンで区切られます。
CoClassAlias生成される IDL やレジストリで使われるクラス名。デフォルトでは、ActiveQt は IDL をコンパイルするために "::" を削除します。
実装カテゴリカンマ区切りのカテゴリー ID (CATID) UUID のリスト。control"、"insertable "などに加えて、追加のコンテナ機能を指定するための一般的なメカニズムです。典型的なCATIDには、CATID_InternetAware ("{0DE86A58-2BAA-11CF-A229-00AA003D7352}")、CATID_SafeForScripting ("{7DD95801-9882-11CF-9FA9-00AA006C42C4}")のほか、ユーザー定義のCATID値がある。

キーも値も大文字と小文字を区別することに注意。

以下は、独自の API のみを公開するクラスのバージョン 2.0 を宣言したもので、Microsoft Office アプリケーションの「オブジェクトの挿入」ダイアログで使用できます。

class MyActiveX : public QWidget
{
    Q_OBJECT
    Q_CLASSINFO("Version", "2.0")
    Q_CLASSINFO("ClassID", "{7a4cffd8-cbcd-4ae9-ae7e-343e1e5710df}")
    Q_CLASSINFO("InterfaceID", "{6fb035bf-8019-48d8-be51-ef05427d8994}")
    Q_CLASSINFO("EventsID", "{c42fffdf-6557-47c9-817a-2da2228bc29c}")
    Q_CLASSINFO("Insertable", "yes")
    Q_CLASSINFO("ToSuperClass", "MyActiveX")
    Q_PROPERTY(...)

public:
    MyActiveX(QWidget *parent = 0);

    ...
};

ライセンス供与されたコンポーネントの開発

コンポーネントを開発する場合、そのコンポーネントをインスタンス化できるユーザを制御したいと思うかもしれません。サーバーのバイナリは、どのクライアントマシンにも出荷して登録することができるため、誰でも自分のソフトウェアでコンポーネントを使用することができます。

例えば、コントロールを作成するコードがライセンスキーを提供したり、コントロールを実行するマシンがライセンスされる必要があります。

Qt クラスをライセンス認証するには、Q_CLASSINFO() マクロを使用して "LicenseKey" を指定します。

class MyLicensedControl : public QWidget
{
    Q_OBJECT
    Q_CLASSINFO("LicenseKey", "<key string>")
    ...
};

このキーは、ライセンスされていないマシン上にMyLicensedControl のインスタンスを作成するために必要です。ライセンスされた開発者は、"LicenseKey "の値を使用してコントロールを作成するアプリケーションと一緒にサーバーバイナリを再配布することができます。

コントロールのライセンス・キーが1つでは十分でない場合(つまり、異なる開発者に異なるライセンス・キーを発行したい場合)、コントロールにライセンスが必要であることを示すために空のキーを指定し、QAxFactory::validateLicenseKey()を再実装して、システム上にライセンスが存在することを確認することができます(ライセンス・ファイルを使用するなど)。

その他のインターフェイス

ActiveQt サーバが提供する ActiveX コントロールは、OLE 仕様を実装するための最小限の COM インターフェイスをサポートしています。ActiveX クラスがQAxBindable クラスを継承する場合、追加の COM インタフェースを実装することもできます。

QAxAggregated の新しいサブクラスを作成し、多重継承を使用して、追加の COM インタフェース・クラスをサブクラス化します。

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

    long queryInterface(const QUuid &iid, void **iface);

    // IUnknown
    QAXAGG_IUNKNOWN

    // ISomeCOMInterface
    ...
}

QAxAggregated::queryInterface() 関数を再実装して、追加の COM インタフェースをサポートします。

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;
}

ISomeCOMInterfaceIUnknown のサブクラスなので、QueryInterface()AddRef()Release() 関数を実装する必要があります。そのためには、クラス定義で QAXAGG_IUNKNOWN マクロを使用します。IUnknown 関数を手動で実装する場合は、QAxAggregated::controllingUnknown() 関数によって返されるインターフェイス・ポインタへの呼び出しを委譲してください。

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

queryInterface() の実装では、IUnknown インターフェース自体をサポートしないでください。

COM インタフェースのメソッドを実装し、コントロールを実装するQObject サブクラスへの呼び出しが必要な場合はQAxAggregated::object() を使用します。

QAxBindable サブクラスでは、QAxBindable::createAggregate() を実装して、QAxAggregated サブクラスの新しいオブジェクトを返します。

class MyActiveX : public QWidget, public QAxBindable
{
    Q_OBJECT

public:
    MyActiveX(QWidget *parent);

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

ActiveQt Frameworkも参照してください

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.