千家信息网

如何开发COM应用程序

发表于:2024-11-11 作者:千家信息网编辑
千家信息网最后更新 2024年11月11日,这期内容当中小编将会给大家带来有关如何开发COM应用程序,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Qt(发音为" cute",而不是" cu-tee")是一个跨
千家信息网最后更新 2024年11月11日如何开发COM应用程序

这期内容当中小编将会给大家带来有关如何开发COM应用程序,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

Qt(发音为" cute",而不是" cu-tee")是一个跨平台框架,通常用作图形工具包,它不仅创建CLI应用程序中也非常有用。而且它也可以在三种主要的台式机操作系统以及移动操作系统(如Symbian,Nokia Belle,Meego Harmattan,MeeGo或BB10)以及嵌入式设备,Android(Necessitas)和iOS的端口上运行。

COM应用程序示例显示了如何使用ActiveQt开发可通过COM自动化的Qt应用程序。不同的基于QObject的类作为与运行Qt应用程序的GUI通信的COM对象公开。这些COM对象的API的设计类似于标准COM应用程序的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代表应用程序对象。它公开了只读属性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 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  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(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(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()前就完成通过单发计时器来确保对插槽的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.ApplicationPrivate MyApp As BooleanPrivate Sub UpdateList()    DocumentList.Clear    DocumentsCount.Caption = Application.documents.Count    For Index = 0 To Application.documents.Count - 1       DocumentList.AddItem (Application.documents.Item(Index).Title)    NextEnd SubPrivate Sub Form_Load()    On Error GoTo CreateNew    Set Application = GetObject(, "comapp.Application")    MyApp = False    GoTo InitializedCreateNew:    On Error GoTo InitializeFailed    Set Application = New Application    Application.Visible = True    MyApp = TrueInitialized:    Caption = Application.id    UpdateListInitializeFailed:End SubPrivate Sub Form_Unload(Cancel As Integer)    If MyApp Then        Application.quit    End IfEnd SubPrivate Sub NewDocument_Click()    Application.documents.addDocument    UpdateListEnd Sub

要构建示例,您必须首先构建QAxServer库。然后运行qmake,将您的制作工具放入examples\activeqt\comapp。

上述就是小编为大家分享的如何开发COM应用程序了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注行业资讯频道。

0