COM アプリの例(ActiveQt)
COM アプリの例では、ActiveQt を使用して COM 経由で自動化できる Qt アプリケーションを開発する方法を示します。さまざまなQObject ベースのクラスが COM オブジェクトとして公開され、実行中の Qt アプリケーションの GUI と通信します。これらのCOMオブジェクトのAPIは、標準的なCOMアプリケーションのAPIに似せて設計されています。
class Application : public QObject { Q_OBJECT Q_CLASSINFO("ClassID", "{b50a71db-c4a7-4551-8d14-49983566afee}") Q_CLASSINFO("InterfaceID", "{4a427759-16ef-4ed8-be79-59ffe5789042}") Q_CLASSINFO("RegisterObject", "yes") Q_PROPERTY(DocumentList* documents READ documents) Q_PROPERTY(QString id READ id) Q_PROPERTY(bool visible READ isVisible WRITE setVisible) public: explicit Application(QObject *parent = nullptr); DocumentList *documents() const; QString id() const { return objectName(); } void setVisible(bool on); bool isVisible() const; QTabWidget *window() const { return m_ui.data(); } public slots: void quit(); private: QScopedPointer <DocumentList> m_docs; QScopedPointer <QTabWidget> m_ui; };
最初のクラスApplication
はアプリケーション・オブジェクトを表します。これは、文書のリストと識別子にアクセスするための読み取り専用のプロパティdocuments
とid
を公開しています。読み書き可能なプロパティvisible
は、アプリケーションのQTabWidget ベースのユーザーインターフェイスを表示するかどうかを制御し、スロットquit()
はアプリケーションを終了します。
RegisterObject属性は、このクラスのインスタンスがCOMの実行オブジェクト・テーブル(ROT)に登録されていることを確認するために設定されます。
class DocumentList : public QObject { Q_OBJECT Q_CLASSINFO("ClassID", "{496b761d-924b-4554-a18a-8f3704d2a9a6}") Q_CLASSINFO("InterfaceID", "{6c9e30e8-3ff6-4e6a-9edc-d219d074a148}") Q_PROPERTY(Application* application READ application) Q_PROPERTY(int count READ count) public: explicit DocumentList(Application *application); int count() const; Application *application() const; public slots: Document *addDocument(); Document *item(int index) const; private: QList<Document *> m_list; };
DocumentList
クラスは、ドキュメントのリストを保存します。これは、ドキュメントの数を読み取ったり、インデックスによって各ドキュメントにアクセスしたり、新しいドキュメントを作成したりするための API を提供します。application
プロパティはルート・オブジェクトを返します。
class Document : public QObject { Q_OBJECT Q_CLASSINFO("ClassID", "{2b5775cd-72c2-43da-bc3b-b0e8d1e1c4f7}") Q_CLASSINFO("InterfaceID", "{2ce1761e-07a3-415c-bd11-0eab2c7283de}") Q_PROPERTY(Application *application READ application) Q_PROPERTY(QString title READ title WRITE setTitle) public: explicit Document(DocumentList *list); virtual ~Document(); Application *application() const; QString title() const; void setTitle(const QString &title); private: QScopedPointer <QWidget> m_page; };
Document
クラスは最終的にアプリケーション内のドキュメントを表します。各ドキュメントはアプリケーションのタブ・ウィジェットのページで表され、ドキュメントのAPIを通して読み書き可能なタイトルを持ちます。application
プロパティは再びルート・オブジェクトを返します。
Document::Document(DocumentList *list) : QObject(list) { QTabWidget *tabs = list->application()->window(); m_page.reset(new QWidget(tabs)); m_page->setWindowTitle(tr("Unnamed")); tabs->addTab(m_page.data(), m_page->windowTitle()); m_page->show(); } Document::~Document() = default; Application *Document::application() const { return qobject_cast<DocumentList *>(parent())->application(); } QString Document::title() const { return m_page->windowTitle(); } void Document::setTitle(const QString &t) { m_page->setWindowTitle(t); QTabWidget *tabs = application()->window(); int index = tabs->indexOf(m_page.data()); tabs->setTabText(index, m_page->windowTitle()); }
Document
クラスの実装は、タブ・ウィジェットに新しいページを作成し、そのページのタイトルを title プロパティに使用します。ページが削除されるのは、ドキュメントが削除されたときです。
DocumentList::DocumentList(Application *application) : QObject(application) { } Application *DocumentList::application() const { return qobject_cast<Application *>(parent()); } int DocumentList::count() const { return m_list.size(); } Document *DocumentList::item(int index) const { return m_list.value(index, nullptr); } Document *DocumentList::addDocument() { Document *document = new Document(this); m_list.append(document); return document; }
DocumentList
の実装は簡単です。
Application::Application(QObject *parent) : QObject(parent), m_ui(new QTabWidget), m_docs(new DocumentList(this)) { setObjectName(QStringLiteral("From QAxFactory")); } DocumentList *Application::documents() const { return m_docs.data(); } void Application::setVisible(bool on) { m_ui->setVisible(on); } bool Application::isVisible() const { return m_ui->isVisible(); } void Application::quit() { m_docs.reset(); m_ui.reset(); QTimer::singleShot(0 /*ms*/, qApp, &QCoreApplication::quit); } #include "main.moc"
Application
クラスはコンストラクタでユーザー・インタフェースを初期化し、setVisible()
の実装で表示と非表示を切り替えます。オブジェクト名(id
プロパティからアクセス可能)は"From
QAxFactory " に設定され、この COM オブジェクトが COM によって作成されたことを示します。QTabWidget を削除するようなデストラクタは存在しないことに注意してください。これは、quit()
スロットで行われ、シングルショットタイマーを介してquit() を呼び出す前に行われます。
QAXFACTORY_BEGIN("{edd3e836-f537-4c6f-be7d-6014c155cc7a}", "{b7da3de8-83bb-4bbe-9ab7-99a05819e201}") QAXCLASS(Application) QAXTYPE(Document) QAXTYPE(DocumentList) QAXFACTORY_END()
クラスは、QAxFactory マクロを使用してサーバーからエクスポートされます。外部からインスタンス化できるのは、Application
オブジェクトのみです。他の API は、Application
API を通じてそれぞれのオブジェクトにアクセスした後にのみ使用できます。
int main(int argc, char *argv[]) { QApplication app(argc, argv); app.setQuitOnLastWindowClosed(false); // started by COM - don't do anything if (QAxFactory::isServer()) return app.exec(); // started by user Application appobject; appobject.setObjectName(QStringLiteral("From Application")); QAxFactory::startServer(); QAxFactory::registerActiveObject(&appobject); appobject.window()->setMinimumSize(300, 100); appobject.setVisible(true); QObject::connect(&app, &QGuiApplication::lastWindowClosed, &appobject, &Application::quit); return app.exec(); }
main()エントリ・ポイント関数は、QApplication を作成し、アプリケーションが COM によって起動されている場合は、イベント・ループに入るだけです。アプリケーションがユーザーによって起動されている場合、Application
オブジェクトが作成され、オブジェクト名が「From Application」に設定されます。その後、COMサーバーが起動し、アプリケーション・オブジェクトがCOMに登録されます。これで、クライアント固有の API を介して COM クライアントからアクセスできるようになります。
COMがアプリケーションを開始した場合、クライアントコードはquit()を呼び出さなければなりません。ユーザーがアプリケーションを開始した場合、最後のウィンドウが閉じられたときにアプリケーションは終了します。
最後に、ユーザー・インターフェースが表示され、イベント・ループが開始されます。
簡単なVisual Basicアプリケーションで、このQtアプリケーションにアクセスすることができます。VBで、新しい "Standard Exe "プロジェクトを開始し、comappLibタイプ・ライブラリへのプロジェクト参照を追加します。リストボックス "DocumentList"、静的ラベル "DocumentsCount"、コマンドボタン "NewDocument "を持つフォームを作成します。最後に、このようなフォームのコードを実装します:
Private Application As comappLib.Application Private MyApp As Boolean Private Sub UpdateList() DocumentList.Clear DocumentsCount.Caption = Application.documents.Count For Index = 0 To Application.documents.Count - 1 DocumentList.AddItem (Application.documents.Item(Index).Title) Next End Sub Private Sub Form_Load() On Error GoTo CreateNew Set Application = GetObject(, "comapp.Application") MyApp = False GoTo Initialized CreateNew: On Error GoTo InitializeFailed Set Application = New Application Application.Visible = True MyApp = True Initialized: Caption = Application.id UpdateList InitializeFailed: End Sub Private Sub Form_Unload(Cancel As Integer) If MyApp Then Application.quit End If End Sub Private Sub NewDocument_Click() Application.documents.addDocument UpdateList End Sub
このサンプルをビルドするには、まずQAxServer ライブラリをビルドする必要があります。次に、qmake
と make ツールをexamples\activeqt\comapp
で実行します。
本ドキュメントに含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。