Пример "COM App" (ActiveQt)
Файлы: Пример "COM App" показывает, как использовать ActiveQt для разработки приложений Qt, которые могут быть автоматизированы посредством COM. Разные классы, основанные на QObject, показаны как COM-объекты, которые соединены с ГПИ запущенного приложения Qt. API этих COM-объектов спроектированы так, чтобы быть похожими на API стандартных приложений COM; т.е., таковые из 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: Application(QObject *parent = 0); DocumentList *documents() const; QString id() const { return objectName(); } void setVisible(bool on); bool isVisible() const; QTabWidget *window() const { return ui; } public slots: void quit(); private: DocumentList *docs; QTabWidget *ui; }; Первый класс Application представляет объект приложения. Он делает видимыми свойства только для чтения documents и id для получения доступа к списку документов и идентификатору. Свойство visible, которое можно читать и записывать, управляет будет ли видим пользовательский интерфейс приложения, основанный на QTabWidget, а слот quit() завершает приложение. Атрибут RegisterObject устанавливается для того, чтобы убедиться, что экземпляры объектов этого класса зарегистрированы в таблице запущенных объектов COM (running object table, 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: DocumentList(Application *application); int count() const; Application *application() const; public slots: Document *addDocument(); Document *item(int index) const; private: QList<Document*> 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: Document(DocumentList *list); ~Document(); Application *application() const; QString title() const; void setTitle(const QString &title); private: QWidget *page; }; Класс Document в конечном счете представляет документ в приложении. Каждый документ представляется страницей в приложении в виджете со вкладками, и имеет заголовок, который можно читать и писать с помощью API документа. Кроме того, свойство application возвращает корневой (root) объект. Document::Document(DocumentList *list) : QObject(list) { QTabWidget *tabs = list->application()->window(); page = new QWidget(tabs); page->setWindowTitle("Unnamed"); tabs->addTab(page, page->windowTitle()); page->show(); } Document::~Document() { delete page; } Application *Document::application() const { return qobject_cast<DocumentList*>(parent())->application(); } QString Document::title() const { return page->windowTitle(); } void Document::setTitle(const QString &t) { page->setWindowTitle(t); QTabWidget *tabs = application()->window(); int index = tabs->indexOf(page); tabs->setTabText(index, page->windowTitle()); } Реализация класса Document создает новую страницу для виджета со вкладками, и использует заголовок этой страницы для свойства заголовка. Страница удаляется когда удаляется документ. DocumentList::DocumentList(Application *application) : QObject(application) { } Application *DocumentList::application() const { return qobject_cast<Application*>(parent()); } int DocumentList::count() const { return list.count(); } Document *DocumentList::item(int index) const { if (index >= list.count()) return 0; return list.at(index); } Document *DocumentList::addDocument() { Document *document = new Document(this); list.append(document); return document; } Реализация DocumentList очень проста. Application::Application(QObject *parent) : QObject(parent), ui(0) { ui = new QTabWidget; setObjectName("From QAxFactory"); docs = new DocumentList(this); } DocumentList *Application::documents() const { return docs; } void Application::setVisible(bool on) { ui->setShown(on); } bool Application::isVisible() const { return ui->isVisible(); } void Application::quit() { delete docs; docs = 0; delete ui; ui = 0; QTimer::singleShot(0, qApp, SLOT(quit())); } #include "main.moc" Класс Application инициализирует пользовательский интерфейс в конструкторе и показывает и скрывает его в реализации setVisible(). Имя объекта (доступный через свойство id) устанавливается равным "From QAxFactory" чтобы отразить, что этот COM-объект был создан с помощью COM. Обратите внимание на то, что нет деструктора, который будет удалять QTabWidget - это делается взамен в слоте quit(), перед вызовом QApplication::quit() посредством однократного (single-shot) таймера, который необходим для обеспечения того, что вызов COM в слот завершен. QAXFACTORY_BEGIN("{edd3e836-f537-4c6f-be7d-6014c155cc7a}", "{b7da3de8-83bb-4bbe-9ab7-99a05819e201}") QAXCLASS(Application) QAXTYPE(Document) QAXTYPE(DocumentList) QAXFACTORY_END() Классы экспортируются с сервера используя макрос QAxFactory. Только объекты класса Application могут быть созданы снаружи - остальные API могут быть использованы только после получения доступа к соответствующим объектам посредством API Application. int main(int argc, char **argv) { QApplication app(argc, argv); app.setQuitOnLastWindowClosed(false); // запущено COM - не делайте ничего if (QAxFactory::isServer()) return app.exec(); // запущено пользователем Application appobject(0); appobject.setObjectName("From Application"); QAxFactory::startServer(); QAxFactory::registerActiveObject(&appobject); appobject.setVisible(true); QObject::connect(qApp, SIGNAL(lastWindowClosed()), &appobject, SLOT(quit())); return app.exec(); } Точка входа функции main() создает QApplication, и только входит в цикл обработки событий, если приложение было запущено COM. Если приложение было запущено пользователем, тогда объект Application создан и имя объекта установлено равным "From Application". Затем запускается COM-сервер и объект приложения регистрируется с помощью COM. Теперь он доступен для клиентов COM через клиенто-специфичные API. Завершение работы приложения контролируется явно - если COM запускает приложение, тогда клиентский код вызывает quit(); если пользователь запускает приложение, тогда приложение завершается когда будет закрыто последнее окно. В заключение, делается видимым пользовательский интерфейс и запускается цикл обработки событий. Простое приложение на Visual Basic может теперь получить доступ к данному приложению Qt. Начните в VB новый проект "Standard Exe" и добавьте ссылку проекта на библиотеку типов comappLib. Создайте форму с окном списка (listbox) "DocumentList", статической меткой "DocumentsCount" и кнопку "NewDocument". В заключение, реализуйте код формы примерно так: 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 Чтобы собрать пример вы должны сначала собрать библиотеку QAxServer. Затем запустите qmake и ваш make-инструмент в каталогеexamples\activeqt\comapp.
|
Попытка перевода Qt документации. Если есть желание присоединиться, или если есть замечания или пожелания, то заходите на форум: Перевод Qt документации на русский язык... Люди внесшие вклад в перевод: Команда переводчиков |