您好,登錄后才能下訂單哦!
這期內(nèi)容當(dāng)中小編將會給大家?guī)碛嘘P(guān)如何開發(fā)COM應(yīng)用程序,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
Qt(發(fā)音為“ cute”,而不是“ cu-tee”)是一個跨平臺框架,通常用作圖形工具包,它不僅創(chuàng)建CLI應(yīng)用程序中也非常有用。而且它也可以在三種主要的臺式機(jī)操作系統(tǒng)以及移動操作系統(tǒng)(如Symbian,Nokia Belle,Meego Harmattan,MeeGo或BB10)以及嵌入式設(shè)備,Android(Necessitas)和iOS的端口上運(yùn)行。
COM應(yīng)用程序示例顯示了如何使用ActiveQt開發(fā)可通過COM自動化的Qt應(yīng)用程序。不同的基于QObject的類作為與運(yùn)行Qt應(yīng)用程序的GUI通信的COM對象公開。這些COM對象的API的設(shè)計類似于標(biāo)準(zhǔn)COM應(yīng)用程序的API。比如Microsoft Office。
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 m_docs; QScopedPointer m_ui; };
第一類Application代表應(yīng)用程序?qū)ο蟆K_了只讀屬性documents、id去訪問文檔列表和標(biāo)識符。讀/寫屬性visible控制應(yīng)用程序基于QTabWidget的用戶界面是否應(yīng)可見,并且插槽quit()終止該應(yīng)用程序。
RegisterObject屬性設(shè)置以確保該類的實例在COM的運(yùn)行對象表(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 m_list; };
該DocumentList級存儲的文件清單。它提供了一個API,可以讀取文檔數(shù)量,按索引訪問每個文檔并創(chuàng)建一個新文檔。該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 m_page; };
該Document類最后表示應(yīng)用程序中的文件。每個文檔均由應(yīng)用程序選項卡小部件中的頁面表示,并可通過文檔API讀取和寫入的標(biāo)題。該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(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(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ù)中的用戶界面,可通過setVisible()實現(xiàn)顯示和隱藏它,其對象名稱(可通過id屬性訪問)設(shè)置為“ "From QAxFactory ”,以指示此COM對象已由COM創(chuàng)建。請注意沒有析構(gòu)函數(shù)可刪除QTabWidget而是在調(diào)用quit()前就完成通過單發(fā)計時器來確保對插槽的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()入口點(diǎn)函數(shù)創(chuàng)建一個QApplication,如果應(yīng)用程序已由COM啟動,則僅進(jìn)入事件循環(huán)。如果應(yīng)用程序已由用戶啟動,則將Application創(chuàng)建對象并將對象名稱設(shè)置為“From Application”。然后啟動COM服務(wù)器,并向COM注冊應(yīng)用程序?qū)ο蟆,F(xiàn)在,COM客戶端可以通過特定于客戶端的API訪問它。
應(yīng)用程序的退出受到顯式控制-如果COM啟動了應(yīng)用程序,則客戶端代碼必須調(diào)用quit(); 如果用戶啟動了該應(yīng)用程序,則該應(yīng)用程序?qū)⒃陉P(guān)閉最后一個窗口時終止。
最后,使用戶界面可見,并啟動事件循環(huán)。
一個簡單的Visual Basic應(yīng)用程序現(xiàn)在可以訪問此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庫。然后運(yùn)行qmake,將您的制作工具放入examples\activeqt\comapp。
上述就是小編為大家分享的如何開發(fā)COM應(yīng)用程序了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。