翻譯|使用教程|編輯:鮑佳佳|2021-02-23 10:15:45.383|閱讀 372 次
概述:COM應(yīng)用程序的例子展示了如何使用ActiveQt來開發(fā)一個可以通過COM自動化的Qt應(yīng)用程序。不同的基于QObject的類被暴露為COM對象,與運行中的Qt應(yīng)用程序的GUI進行通信。這些COM對象的API被設(shè)計成類似于標(biāo)準(zhǔn)COM應(yīng)用程序的API,即那些來自Microsoft Office的API。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關(guān)鏈接:
Qt相關(guān)組件:
COM應(yīng)用程序的例子展示了如何使用ActiveQt來開發(fā)一個可以通過COM自動化的Qt應(yīng)用程序。不同的基于QObject的類被暴露為COM對象,與運行中的Qt應(yīng)用程序的GUI進行通信。這些COM對象的API被設(shè)計成類似于標(biāo)準(zhǔn)COM應(yīng)用程序的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代表應(yīng)用對象。它公開了只讀屬性documents和id來獲取對文檔列表的訪問,以及一個標(biāo)識符。一個讀/寫屬性visible控制應(yīng)用程序基于QTabWidget的用戶界面是否應(yīng)該可見,一個槽quit()終止應(yīng)用程序。
RegisterObject屬性被設(shè)置為確保該類的實例在COM的運行對象表(ROT)中被注冊--這允許COM客戶端連接到一個已經(jīng)實例化的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來讀取文檔的數(shù)量,通過索引訪問每個文檔,并創(chuàng)建新的文檔。它提供了一個API來讀取文檔的數(shù)量,通過索引訪問每個文檔并創(chuàng)建一個新的文檔。應(yīng)用屬性返回根對象。
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類最后代表應(yīng)用程序中的一個文檔。每個文檔由應(yīng)用程序的標(biāo)簽部件中的一個頁面來表示,并且有一個標(biāo)題,這個標(biāo)題是可以通過文檔的API來讀寫的。應(yīng)用程序?qū)傩栽俅畏祷馗鶎ο蟆?
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該類的實現(xiàn)為選項卡小部件創(chuàng)建一個新頁面,并將該頁面的標(biāo)題用作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實現(xiàn)是直接的。
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類初始化構(gòu)造函數(shù)中的用戶界面,以及顯示和隱藏它的實現(xiàn)setVisible()。對象名稱(可通過id屬性訪問)設(shè)置為“ "From QAxFactory ”,以指示此COM對象已由COM創(chuàng)建。請注意,沒有析構(gòu)函數(shù)可刪除QTabWidget-而是quit()在調(diào)用quit( )通過單次計時器進行,這是確保對插槽的COM調(diào)用完成所必需的。
QAXFACTORY_BEGIN("{edd3e836-f537-4c6f-be7d-6014c155cc7a}", "{b7da3de8-83bb-4bbe-9ab7-99a05819e201}") QAXCLASS(Application) QAXTYPE(Document) QAXTYPE(DocumentList) QAXFACTORY_END()
使用QAxFactory宏從服務(wù)器導(dǎo)出類。只能Application從外部實例化對象-其他API只能在訪問整個ApplicationAPI中的相應(yīng)對象后才能使用。
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()切入點函數(shù)創(chuàng)建一個QApplication,如果應(yīng)用程序是由COM啟動的,則進入事件循環(huán)即可。如果應(yīng)用程序已被用戶啟動,則創(chuàng)建Application對象,并將對象名設(shè)置為 "From Application"。然后啟動COM服務(wù)器,并將應(yīng)用對象注冊到COM中。現(xiàn)在,COM客戶端可以通過客戶端特定的API來訪問它。
應(yīng)用程序的退出是顯式控制的--如果COM啟動了應(yīng)用程序,那么客戶端代碼必須調(diào)用quit();如果用戶啟動了應(yīng)用程序,那么當(dāng)最后一個窗口被關(guān)閉時,應(yīng)用程序就會終止。
最后,使用戶界面可見,并啟動事件循環(huán)。
現(xiàn)在,一個簡單的Visual Basic應(yīng)用程序可以訪問這個Qt應(yīng)用程序。在VB中,啟動一個新的 "Standard Exe "項目,并向comappLib類型庫添加一個項目引用。創(chuàng)建一個具有列表框 "DocumentList"、靜態(tài)標(biāo)簽 "DocumentsCount "和命令按鈕 "NewDocument "的窗體。最后,像這樣實現(xiàn)表單的代碼。
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
要構(gòu)建示例,您必須首先構(gòu)建QAxServer庫。然后運行qmake,將您的制作工具放入examples\activeqt\comapp。
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉(zhuǎn)載自: