COM应用程序的例子展示了如何使用ActiveQt来开发一个可以通过COM自动化的Qt应用程序。不同的基于QObject的类被暴露为COM对象,与运行中的Qt应用程序的GUI进行通信。这些COM对象的API被设计成类似于标准COM应用程序的API,即那些来自Microsoft Office的API。
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。
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.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,将您的制作工具放入examplesactiveqtcomapp。

标签:
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!