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.rc
とqaxserver.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() マクロを使用します。ClassID
とInterfaceID
は必須ですが、EventsID
はオブジェクトにシグナルがある場合にのみ必要です。これらの識別子を生成するには、uuidgen
やguidgen
などのシステム・ツールを使用します。
詳細は「クラス情報とチューニング」を参照してください。
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 |
QString | BSTR |
int | int |
uint | 符号なしint |
double | double |
qlonglong | CY |
qulonglong | CY |
QColor | OLE_COLOR |
QDate | 日付 |
QDateTime | 日付 |
QTime | 日付 |
QFont | IFontDisp*(フォントディスプ |
QPixmap | IPictureDisp* |
QVariant | バリアント |
QVariantList ( < >と同じ)QListQVariant | safearray(バリアント) |
QStringList | セーフアレイ(bstr) |
QByteArray | safearray(バイト) |
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] OLE_COLOR & [in, out] OLE_COLOR*. | [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<QVariant | in, 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 つの一意な識別子を使用してシステム・レジストリに登録する必要があります。これらの識別子は、guidgen
やuuidgen
などのツールによって提供されます。登録情報によって、COM は要求された ActiveX コントロールを提供するバイナリをローカライズし、コントロールへのリモートプロシージャコールをマーシャルし、コントロールが公開するメソッドとプロパティに関する型情報を読み取ることができます。
クライアントからの要求に応じて COM オブジェクトを作成するには、サーバーがQAxFactory の実装をエクスポートする必要があります。これを行う最も簡単な方法は、一連のマクロを使用することです:
QAXFACTORY_BEGIN("{ad90301a-849e-4e8b-9a91-0a6dc5f6461f}", "{a8f21901-7ff7-4f6a-b939-789620c03d83}") QAXCLASS(MyWidget) QAXCLASS(MyWidget2) QAXTYPE(MySubType) QAXFACTORY_END()
これは、MyWidget
とMyWidget2
を COM クライアントが作成できる COM オブジェクトとしてエクスポートし、MySubType
をMyWidget
とMyWidget2
のプロパティとパラメータで使用できる型として登録します。
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 サブクラスに適切なコンストラクタがありません。ファクトリクラスに
のようなパブリッククラスのコンストラクタを用意してください。
"構文エラー: 番号の接尾辞が正しくありません"
一意の識別子が、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アプリケーションもサポートされていますが、コントロールを "Insertable "オブジェクトとして登録する必要があります。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 を再実装する必要があります。 |
EventsID | イベント・インターフェース 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; }
ISomeCOMInterface
はIUnknown
のサブクラスなので、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も参照してください 。
本ドキュメントに含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。