點選下載下傳Qt6最新試用版
COM應用程式的例子展示了如何使用ActiveQt來開發一個可以通過COM自動化的Qt應用程式。不同的基于QObject的類被暴露為COM對象,與運作中的Qt應用程式的GUI進行通信。這些COM對象的API被設計成類似于标準COM應用程式的API,即那些來自Microsoft Office的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)中被注冊--這允許COM用戶端連接配接到一個已經執行個體化的COM對象。
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:
QVector<Document *> m_list;
};
DocumentList類存儲了一個文檔的清單,它提供了一個API來讀取文檔的數量,通過索引通路每個文檔,并建立新的文檔。它提供了一個API來讀取文檔的數量,通過索引通路每個文檔并建立一個新的文檔。應用屬性傳回根對象。
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來讀寫的。應用程式屬性再次傳回根對象。
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.count();
}
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( )通過單次計時器進行,這是確定對插槽的COM調用完成所必需的。
QAXFACTORY_BEGIN("{edd3e836-f537-4c6f-be7d-6014c155cc7a}", "{b7da3de8-83bb-4bbe-9ab7-99a05819e201}")
QAXCLASS(Application)
QAXTYPE(Document)
QAXTYPE(DocumentList)
QAXFACTORY_END()
使用QAxFactory宏從伺服器導出類。隻能Application從外部執行個體化對象-其他API隻能在通路整個ApplicationAPI中的相應對象後才能使用。
int main(int argc, char *argv[])
{
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
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中。現在,COM用戶端可以通過用戶端特定的API來通路它。
應用程式的退出是顯式控制的--如果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,将您的制作工具放入examples\activeqt\comapp。
Qt相關元件:
- QtitanRibbon| 下載下傳試用: 遵循Microsoft Ribbon UI Paradigm for Qt技術的Ribbon UI元件,緻力于為Windows、Linux和Mac OS X提供功能完整的Ribbon元件。
- QtitanChart | 下載下傳試用 :是一個C ++庫,代表一組控件,這些控件使您可以快速地為應用程式提供漂亮而豐富的圖表。并且支援所有主要的桌面作業系統。
- QtitanDataGrid | 下載下傳試用 :這個Qt資料網格元件使用純C++建立,運作速度極快,處理大資料和超大資料集的效果突出。QtitanDataGrid完全內建了QtDesigner,因而極易适應其他相似的開發環境,保證100%相容Qt GUI。