溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何開發(fā)COM應(yīng)用程序

發(fā)布時間:2021-12-21 11:14:40 來源:億速云 閱讀:115 作者:柒染 欄目:大數(shù)據(jù)

這期內(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è)資訊頻道。

向AI問一下細(xì)節(jié)

免責(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)容。

com
AI