[Предыдущая: Модуль QAxContainer] [Модули Qt] [Следующая: Модуль QtDBus] Модуль QAxServer
|
QAxAggregated | Абстрактный базовый класс для реализаций дополнительных COM-интерфейсов |
---|---|
QAxBindable | Интерфейс между QWidget и клиентом ActiveX |
QAxFactory | Определяет фабрику для создания COM-компонентов |
The QAxServer module is part of the ActiveQt framework. Оно состоит из трех классов:
Предоставляются несколько примеров реализации элементов управления ActiveX и COM-объектов.
Темы:
To turn a standard Qt application into a COM server using the QAxServer library you must add qaxserver as a CONFIG setting in your .pro file.
Внепроцессный исполняемый файл сервера генерируется из .pro файла примерно так:
TEMPLATE = app CONFIG += qaxserver RC_FILE = qaxserver.rc ...
Чтобы собрать внутрипроцессный сервер используйте .pro файл, например так:
TEMPLATE = lib CONFIG += qaxserver dll DEF_FILE = qaxserver.def RC_FILE = qaxserver.rc ...
Файлы qaxserver.rc и qaxserver.def являются частью каркаса и могут быть использованы из своих обычных мест расположения (путь указывается в .pro файле) или скопированы в каталог проекта. Вы можете изменять эти файлы до тех пор, пока они включают в себя любой файл как запись библиотеки типов, т.е. вы можете добавить информацию о версии или указать другую пиктограмму панели инструментов.
Конфигурация qaxserver вынудит инструмент qmake добавить требуемые шаги сборки к системе сборки:
Note that the QAxServer build system is not supported on Windows 98/ME (attaching of resources to a binary is not possible there), but a server built on Windows NT/2000/XP will work on previous Windows versions as well.
Чтобы пропустить этап постобработки установите также конфигурацию qaxserver_no_postlink.
Дополнительно вы можете указать номер версии используя переменную VERSION, например
TEMPLATE = lib VERSION = 2.5 ...
Указанный номер версии будет использовать в качестве версии библиотеки типов и сервера при регистрации.
Будет ли ваш COM-сервер запущен как автономный исполняемый файл или как разделяемая библиотека в процессе клиента зависит главным образом от типа COM-объектов которые вы хотите предоставить в сервере.
Исполняемый файл сервера имеет преимущество being able to запущен как автономное приложение, но добавляет значительные накладные расходы на связь между клиентом COM и COM-объектом. Если в элементе управления происходит программная ошибка, то только запущенный элементом управления серверный процесс аварийно завершит работу, а клиентское приложение скорее всего продолжит работу. Не все клиенты COM поддерживают исполняемые файлы серверов.
Внутрипроцессный сервер обычно меньше по размеру и быстрее запускается. Связь между клиентом и сервером выполняется непосредственно через вызовы виртуальных функций и не привносит накладные расходы требуемые для удаленных вызовов процедур. Однако, если сервер аварийно завершит работу клиентское приложение вероятно также аварийно заверится, и не вся функциональность доступна для внутрипроцессных серверов (т.е., регистрация в таблице исполняющихся объектов COM).
Оба типа серверов могут использовать Qt либо как разделяемую библиотеку, либо статически слинкованную в серверную библиотеку.
Для связанных с ActiveQt шагов постобработки для работы сервера нужно удовлетворить некоторые требования:
Если эти требования не выполнены, то возможно произойдет одна или более из следующих ошибок:
Чтобы сгенерировать IDL виджетов, открытых как элементы управления ActiveX, необходимо создать экземпляр класса (вызывается конструктор). На этой стадии не существует ничего кроме объекта QApplication. Конструктор вашего виджета не должен полагаться на какие-либо другие созданные объекты, например, он будет проверять на ненулевые указатели.
Чтобы отладить ваш сервер, запустите его с ключом -dumpidl выходной файл и проверьте, где он аварийно завершается.
Обратите внимание на то, что функции элемента управления не вызываются.
Прикрепление библиотеки типов повреждает бинарный файл сервера. Это ошибка в Windows и случается только в релизных сборках.
Первый шаг линковки заключается в линковке пустой библиотеки типов в исполняемый файл, который idc позднее может заменить. Добавим файл ресурса с библиотекой типов к вашему проекту как продемонстрировано в примерах.
Системе сборки нужно запустить исполняемый файл сервера для генерирования определения интерфейса и зарегистрировать сервер. Если динамически слинкованная библиотека, с которой слинкован сервер, не находится в пути это может вызвать аварийное завершение работы (например, вызовы Visual Studio сервера используя установки окружения, указанные в опции "Directories"). Убедитесь, что все DLLки, требуемые вашему серверу, расположены в каталоге, который перечислен в путях как напечатано в окне сообщения ошибки.
Сервер ActiveX не может выключиться когда последний клиенты перестал его использовать. Обычно для завершения приложения требуется около двух секунд, но вы можете использовать диспетчер задач, чтобы убить процесс (например, когда клиент не освобождает элементы управления должным образом).
Чтобы реализовать COM-объект с помощью Qt, создайте подкласс QObject или любой существующий подкласс QObject. Если класс является подклассом QWidget, COM-объект будет элементов управления ActiveX.
#include <QWidget> class MyActiveX : public QWidget { Q_OBJECT
Макрос Q_OBJECT требуется для предоставления каркасу ActiveQt метаобъектной информации о виджете.
Q_CLASSINFO("ClassID", "{1D9928BD-4453-4bdd-903D-E525ED17FDE5}") Q_CLASSINFO("InterfaceID", "{99F6860E-2C5A-42ec-87F2-43396F4BE389}") Q_CLASSINFO("EventsID", "{0A3E9F27-E4F1-45bb-9E47-63099BCCD0E3}")
Используйте макрос Q_CLASSINFO() для указания идентификаторов COM для COM-объекта. ClassID и InterfaceID требуются пока EventsID необходим только когда ваш объект имеет сигналы. Чтобы сгенерировать эти идентификаторы используйте системные инструменты, аналогичные uuidgen или guidgen.
Вы можете указать дополнительные атрибуты для каждого из ваших классов; за подробностями обращайтесь к Информация о классе и настройка.
Q_PROPERTY(int value READ value WRITE setValue)
Используйте макрос Q_PROPERTY() для объявления свойств элемента управления ActiveX.
Объявите стандартный конструктор, получающий родительский объект, и функции, сигналы и слоты аналогичные для любого подкласса QObject.
public: MyActiveX(QWidget *parent = 0) ... int value() const; public slots: void setValue(int v); ... signals: void valueChange(int v); ... };
Каркас ActiveQt открывает свойства и открытые слоты в качестве свойств ActiveX и методы, а сигналы как события ActiveX, а также конвертировать между типами данных Qt и эквивалентными типами данных COM.
Типы данных Qt, поддерживаемых для свойств:
Тип данных Qt | Свойство COM |
---|---|
bool | VARIANT_BOOL |
QString | BSTR |
int | int |
uint | unsigned int |
double | double |
qlonglong | CY |
qulonglong | CY |
QColor | OLE_COLOR |
QDate | DATE |
QDateTime | DATE |
QTime | DATE |
QFont | IFontDisp* |
QPixmap | IPictureDisp* |
QVariant | VARIANT |
QVariantList (то же что и QList<QVariant>) | SAFEARRAY(VARIANT) |
QStringList | SAFEARRAY(BSTR) |
QByteArray | SAFEARRAY(BYTE) |
QRect | Определяемый пользователем тип |
QSize | Определяемый пользователем тип |
QPoint | Определяемый пользователем тип |
Типы данных Qt, которые поддерживаются для параметров сигналов и слотов:
Тип данных Qt | Параметр COM |
---|---|
bool | [in] VARIANT_BOOL |
bool& | [in, out] VARIANT_BOOL* |
QString, const QString& | [in] BSTR |
QString& | [in, out] BSTR* |
QString& | [in, out] BSTR* |
int | [in] int |
int& | [in,out] int |
uint | [in] unsigned int |
uint& | [in, out] unsigned int* |
double | [in] double |
double& | [in, out] double* |
QColor, const QColor& | [in] OLE_COLOR |
QColor& | [in, out] OLE_COLOR* |
QDate, const QDate& | [in] DATE |
QDate& | [in, out] DATE* |
QDateTime, const QDateTime& | [in] DATE |
QDateTime& | [in, out] DATE* |
QFont, const QFont& | [in] IFontDisp* |
QFont& | [in, out] IFontDisp** |
QPixmap, const QPixmap& | [in] IPictureDisp* |
QPixmap& | [in, out] IPictureDisp** |
QList<QVariant>, const QList<QVariant>& | [in] SAFEARRAY(VARIANT) |
QList<QVariant>& | [in, out] SAFEARRAY(VARIANT)* |
QStringList, const QStringList& | [in] SAFEARRAY(BSTR) |
QStringList& | [in, out] SAFEARRAY(BSTR)* |
QByteArray, const QByteArray& | [in] SAFEARRAY(BYTE) |
QByteArray& | [in, out] SAFEARRAY(BYTE)* |
QObject* | [in] IDispatch* |
QRect& | [in, out] struct QRect (user defined) |
QSize& | [in, out] struct QSize (определяется пользователем) |
QPoint& | [in, out] struct QPoint (определяется пользователем) |
Также поддерживаются экспортируемые перечисления и флаги (смотрите Q_ENUMS() и Q_FLAGS()). Внутрипараметрические (in-parameter) типы также поддерживаются как возвращаемые значения.
Свойства и сигналы/слоты, которые имеют параметры, использующие любые другие типы данных, игнорируются каркасом ActiveQt.
COM-объекты может иметь множество подобъектов, которые могут представлять субэлемент COM-объекта. COM-объект, отображающий приложение многодокументной электронной таблицы, может предоставить например один подобъект для каждого листа таблицы.
Любой подкласс QObject можно использовать в качестве типа для подобъекта в ActiveX, если он известен QAxFactory. Затем тип можно использовать в свойствах, или в качестве возвращаемого типа или параметра слота.
Чтобы сделать свойства связываемыми для клиента ActiveX, используйте множественное наследование от класса QAxBindable:
#include <QAxBindable> #include <QWidget> class MyActiveX : public QWidget, public QAxBindable { Q_OBJECT
При реализации функций записи свойства используйте функции класса QAxBindable - requestPropertyChange() и propertyChanged() - чтобы позволить клиентам ActiveX привязать свойства к элементу управления.
Чтобы сделать COM-сервер доступны для системы COM нужно его зарегистрировать в системном реестре используя пять уникальных идентификаторов. Эти идентификаторы предоставляются инструментами тип guidgen или uuidgen. Информация о регистрации позволяет COM для локализации бинарного файла, предоставляемого запрашиваемым элементом управления ActiveX, передавать (marshall) вызовы удаленных процедур для элемента управления и прочитать информацию типов о методах и свойствах отрытых элементом управления.
Чтобы создать COM-объект при запросе клиента своего сервера должны экспортировать реализацию QAxFactory. Самым лёгким способом сделать это - использовать набор макросов:
QAXFACTORY_BEGIN("{ad90301a-849e-4e8b-9a91-0a6dc5f6461f}", "{a8f21901-7ff7-4f6a-b939-789620c03d83}") QAXCLASS(MyWidget) QAXCLASS(MyWidget2) QAXTYPE(MySubType) QAXFACTORY_END()
Это экспортирует MyWidget и MyWidget2 как COM-объекты, которые могут быть созданы клиентами COM и будет зарегистрирован MySubType как тип, который может быть использован в свойствах и параметрах MyWidget и MyWidget2.
Документация класса QAxFactory объясняет как использовать этот макрос и как реализовать и использовать пользовательские фабрики.
Для внепроцессных исполняемых файлов серверов вы можете реализовать функцию main() чтобы создать экземпляр объекта QApplication и войти в цикл обработки событий так же как любое обычное приложение Qt. По умолчанию приложение будет запущено как стандартное приложение Qt, но если вы передадите -activex в командной строке то оно будет запущено как сервер ActiveX. Используйте QAxFactory::isServer() для создания и запуска стандартного интерфейса приложения, или для предотвращения автономного выполнения:
#include <QApplication> #include <QAxFactory> int main(int argc, char *argv[]) { QApplication app(argc, argv); if (!QAxFactory::isServer()) { // создаём и показываем главное окно } return app.exec(); }
Этого однако не требуется так как ActiveQt предоставляет реализацию по умолчанию функции main. Реализация по умолчанию вызывает QAxFactory::startServer(), создаёт экземпляр класса QApplication и вызывает exec().
Чтобы собрать исполняемый файл сервера ActiveX запустите qmake для генерации make-файла, и используйте make-инструмент вашего компилятора как любого другого приложения Qt. Процесс создания будет также регистрировать элементы управления в системном реестре вызывая получившийся исполняемый файл с опцией -regserver командной строки.
Если сервер ActiveX является исполняемым файлом, то поддерживаются следующие опции командной строки:
Опция | Результат |
---|---|
-regserver | Регистрируем сервер в системном реестре |
-unregserver | Отменяем регистрацию сервера в системном реестре |
-activex | Запускаем приложение как ActiveX-сервер |
-dumpidl <file> -version x.y | Записываем IDL сервера в указанный файл. Библиотека типов будет иметь версию x.y |
Внутрипроцессные сервера могут быть зарегистрированы используя инструмент regsvr32, доступный на всех системах Windows.
Перечисленные ошибки компилятора/линкера основаны на таких проблемах компилятора Microsoft Visual C++ 6.0.
Когда произойдёт ошибка в коде, который использует макрос QAXFACTORY_DEFAULT(), класс виджета не имеет конструктора, который может быть использован фабрикой по умолчанию. Либо добавьте стандартный конструктор виджета, либо реализуйте пользовательскую фабрику, которой он не требуется.
Когда произойдёт ошибка в коде, который использует макрос QAXFACTORY_EXPORT(), подкласс QAxFactory не имеет соответствующего конструктора. Предоставьте общий конструктор класса, похожий на
MyFactory(const QUuid &, const QUuid &);
для вашего класса фабрики.
Уникальные идентификаторы не могут быть переданы как строки в макрос QAXFACTORY_EXPORT() или QAXFACTORY_DEFAULT().
Сервер не экспортирует реализацию QAxFactory. Используйте макрос QAXFACTORY_EXPORT() в одном из файлов реализации для создания экземпляра класса и экспорта фабрики, или используйте макрос QAXFACTORY_DEFAULT() для использования фабрики по умолчанию.
Сервер экспортирует более, чем одну реализацию QAxFactory или экспортирует одну и туже реализацию дважды. Если вы используете фабрику по умолчанию, то макрос QAXFACTORY_DEFAULT() должен использоваться в проекте только один раз. Используйте пользовательскую реализацию QAxFactory и макрос QAXFACTORY_EXPORT(), если сервер предоставляет множество элементов управления ActiveX.
Сервера ActiveX написанные с помощью Qt могут использовать Qt либо как разделяемую библиотеку, либо имеют Qt, слинкованную статически в бинарный файл. В результате обоих способов получаются весьма большие пакеты (либо сам бинарный файл сервера становится больше, либо вы поставляет Qt DLL).
Если ваш сервер ActiveX может быть запущен также как автономное приложение, запустите исполняемый файл сервера с параметром командной строки -regserver после установки исполняемого файла на целевой системе. После этого элементы управления, предоставляемые сервером, станут доступными для клиентов ActiveX.
Если ваш сервер ActiveX является частью установочного пакета, то используйте инструмент regsvr32, предоставляемый Microsoft, чтобы зарегистрировать элементы управления в целевой системе. Если этого инструмента нет, загрузите DLL в ваш процесс установки, разрешите символ DllRegisterServer и вызовите функцию:
HMODULE dll = LoadLibrary("myserver.dll"); typedef HRESULT(__stdcall *DllRegisterServerProc)(); DllRegisterServerProc DllRegisterServer = (DllRegisterServerProc)GetProcAddress(dll, "DllRegisterServer"); HRESULT res = E_FAIL; if (DllRegisterServer) res = DllRegisterServer(); if (res != S_OK) // обработка ошибки
Если вы хотите использовать элементы управления вашего сервера в веб-страницах, вам нужно сделать доступным сервер для браузера, используемого для просмотра вашей страницы, и вам нужно указать расположение пакета сервера в вашей странице.
Чтобы указать расположение сервера используйте атрибут CODEBASE тега OBJECT вашего веб-сайта. Значение может указывать на сам файл сервера, на INF-файл, перечисляющий другие файлы требуемые серверу (например, DLL Qt), или сжатый архив CAB.
Файлы INF и CAB документированы почти в каждой доступной книге о программировании ActiveX и COM также, как и в библиотеке MSDN и различных онлайн ресурсах. Примеры включают INF-файлы, которые могут быть использованы для сборки архивов CAB:
[version] signature="$CHICAGO$" AdvancedINF=2.0 [Add.Code] simpleax.exe=simpleax.exe [simpleax.exe] file-win32-x86=thiscab clsid={DF16845C-92CD-4AAB-A982-EB9840E74669} RegisterServer=yes
Инструмент CABARC от Microsoft легко может генерировать архивы CAB:
cabarc N simpleax.cab simpleax.exe simple.inf
INF-файлы допускают статическую сборку Qt, поэтому зависимости от других DLL не перечисляются в INF-файлах. Чтобы распространить DLLки, от которых зависит сервер ActiveX, вы должны добавить зависимости и предоставить библиотечные файлы с архивом.
Чтобы использовать элементы управления ActiveX, например, для встраивания их в веб-страницу, используйте HTML-тег <object>.
<object ID="MyActiveX1" CLASSID="CLSID:ad90301a-849e-4e8b-9a91-0a6dc5f6461f"> ... <\object>
To initialize the control's properties, use
<object ID=...> <param name="name" value="value"> <\object>
Если веб-браузер поддерживает выполнение скриптов используйте JavaScript, VBScript и формы для сценария элемента управления. The ActiveQt examples include demonstration HTML pages for the example controls.
Нижеследующее в значительной мере базируется на наших экспериментах с элементами управления ActiveX и клиентскими приложениями, и никоим образом не являются исчерпывающими.
Эти стандартные приложения работают с элементами управления ActiveX, разработанными с помощью ActiveQt. Обратите внимание на то, что некоторые клиенты поддерживают только внутрипроцессные элементы управления.
Приложения Microsoft Office поддерживаются, но вам нужно зарегистрировать элементы управления как "Insertable" объекты. Переопределите QAxFactory::registerClass чтобы добавить этот атрибут к классу COM, или установите "Insertable" информацию класса для вашего класса равной "yes" используя макрос Q_CLASSINFO.
Мы не сумели заставить работать COM-объекты, основанные на ActiveQt, со следующими клиентскими приложениями.
Если система не может запустить сервер (проверьте с помощью менеджера задач запущен ли процесс сервера), убедитесь что DLL, от которых зависит сервер, присутствуют в системных путях (например, Qt DLL!). Используйте dependency walker чтобы увидеть все зависимости бинарного файла сервера.
Если сервер запущен (например, есть в списке менеджера задач), информацию по отладке вашего сервера смотрите в следующем разделе.
Если сервер может быть собран и правильно зарегистрирован во время процесса сборки, но объект не может быть инициализирован, например, приложение OLE/COM Object Viewer, убедитесь, что DLL, от которых зависит сервер, присутствуют в системных путях (например, Qt DLL). Используйте dependency walker чтобы увидеть все зависимости бинарного файла сервера.
Если сервер запущен, информацию по отладке вашего сервера смотрите в следующем разделе.
Чтобы отладить внутрипроцессный сервер в Visual Studio установите проект сервера в качестве активного проекта и укажите клиент "executable for debug session" в настройках проекта (например, используйте Тестовый контейнер ActiveX). Вы можете установить точки останова в вашем коде, а также пройти по шагам код ActiveQt и Qt если вы установили отладочную версию.
Для отладки исполняемого файла сервера запустите приложение в отладчике и начните с параметра командной строки -activex. Затем запустите своего клиента и создайте экземпляр вашего элемента управления ActiveX. COM будет использовать существующий процесс для следующего клиента пытающегося создать элемент управления ActiveX.
Чтобы предоставить атрибуты для каждого класса COM используйте макрос Q_CLASSINFO, являющийся частью мета-объектной системы Qt.
Ключ | Смысл значения |
---|---|
Версия | Версия класса (по умолчанию 1.0) |
Описание | Строка описания класса. |
ClassID | Идентификатор класса. Вы должны переопределить QAxFactory::classID если не задан. |
InterfaceID | Идентификатор интерфейса. Вы должны переопределить QAxFactory::interfaceID если не задан. |
EventsID | Идентификатор интерфейса события. Нет сигналов, открытых как события COM, если не указано. |
DefaultProperty | Свойство, задающее представление свойства этого класса по умолчанию. Т.е. свойство кнопки по умолчанию будет "text". |
DefaultSignal | Сигнал, задающий представление сигнала этого класса по умолчанию. Т.е. сигнал кнопки по умолчанию будет "clicked". |
LicenseKey | Создание объекта требует указания лицензионного ключа. Ключ может быть пустым что требует лицензионный механизм. По умолчанию классы не лицензированы. Смотрите также следующий раздел. |
StockEvents | Объекты делают видимыми события запаса если значение равно "yes". Смотрите QAxFactory::hasStockEvents() |
ToSuperClass | Объекты делают видимыми функциональность всех суперклассов выше по иерархии и включая класс с именем в значении. Смотрите QAxFactory::exposeToSuperClass() |
Insertable | Если значение равно "yes", класс регистрируется как "Insertable" и будет приведён в списке контейнеров OLE 2 (т.е. Microsoft Office). Этот атрибут по умолчанию не установлен. |
Aggregatable | Если значение равно "no", класс не поддерживают агрегацию. По умолчанию агрегация поддерживается. |
Creatable | Если значение равно "no", класс не может быть создан клиентом и доступен только через API другого класса (т.е. класс является подтипом). |
RegisterObject | Если значение равно "yes", объекты этого класса регистрируются с помощью OLE и доступны из таблицы запущенных объектов (т.е. клиенты могут присоединиться к уже запущенному экземпляру объекта этого класса). Этот атрибут поддерживается только во внепроцессных серверах. |
MIME | Объект может обработать данные и файлы формата, указанного в значении. Значение имеет формат mime:extension:description. Множественные форматы разделяются точкой с запятой. |
CoClassAlias | Имя класса, используемого в сгенерированном IDL и в реестре. Это особенно useful for C++ classes that live in a namespace - by default, ActiveQt just removes the "::" to make the IDL compile. |
Обратите внимание на то, что и ключи, и значения являются чувствительными к регистру.
Нижеследующее объявляет версию 2.0 класса, который делает видимым только свой собственный API, и доступен в диалоге "Insert Objects" приложений Microsoft Office.
class MyActiveX : public QWidget { Q_OBJECT Q_CLASSINFO("Version", "2.0") Q_CLASSINFO("ClassID", "{7a4cffd8-cbcd-4ae9-ae7e-343e1e5710df}") Q_CLASSINFO("InterfaceID", "{6fb035bf-8019-48d8-be51-ef05427d8994}") Q_CLASSINFO("EventsID", "{c42fffdf-6557-47c9-817a-2da2228bc29c}") Q_CLASSINFO("Insertable", "yes") Q_CLASSINFO("ToSuperClass", "MyActiveX") Q_PROPERTY(...) public: MyActiveX(QWidget *parent = 0); ... };
Если вы разрабатываете компоненты, вы может захотеть контролировать кто может создавать экземпляры этих компонентов. Поскольку бинарный файл сервера может распространяться и регистрироваться на любой клиентской машине, любой может использовать эти компоненты в своём программного обеспечении.
Лицензирование компонентов может быть произведено используя разнообразные приёмы, например, код создания элемента управления может предоставлять лицензионный ключ или механизм, в котором предполагается запускать элемент управления, требует лицензирования.
Чтобы пометить класс Qt как лицензированный укажите "LicenseKey" используя макрос Q_CLASSINFO().
class MyLicensedControl : public QWidget { Q_OBJECT Q_CLASSINFO("LicenseKey", "<key string>") ... };
Ключ требуется чтобы иметь возможность создать экземпляр класса MyLicensedControl на машине, которая не лицензирует сам сеяб. Лицензированный разработчик теперь может повторно распространять бинарный файл сервера со своим приложением, которое создаёт элемент управления используя значение "LicenseKey" до тех пор, пока пользователи приложения не смогут создать элемент управления мез лицензионного ключа.
Если единственного лицензионного ключа для элемента управления недостаточно (т.е. вы хотите различать разработчиков чтобы запрашивать разные лицензионные ключи), вы можете указать пустой ключ чтобы покачать, что элементу управления требуется лицензия, и переопределить QAxFactory::validateLicenseKey() для проверки того, что лицензия существует в системе (т.е. через файл лицензии).
Элементы управления ActiveX, предоставленные серверами ActiveQt, поддерживают минимальный набор интерфейсов COM для реализации спецификаций OLE. Если класс ActiveX унаследован от класса QAxBindable, он также может реализовать дополнительные интерфейсы COM.
Создайте новый подкласс QAxAggregated и используйте множественное наследование для создание подкласса дополнительного интерфейса классов COM.
class AxImpl : public QAxAggregated, public ISomeCOMInterface { public: AxImpl() {} long queryInterface(const QUuid &iid, void **iface); // IUnknown QAXAGG_IUNKNOWN // ISomeCOMInterface ... }
Переопределите функцию QAxAggregated::queryInterface() для поддержки дополнительных интерфейсов COM.
long AxImpl::queryInterface(const QUuid &iid, void **iface) { *iface = 0; if (iid == IID_ISomeCOMInterface) *iface = (ISomeCOMInterface *)this; else return E_NOINTERFACE; AddRef(); return S_OK; }
Поскольку ISomeCOMInterface - подкласс IUnknown, вам нужно реализовать функции QueryInterface(), AddRef() и Release(). Чтобы сделать это используйте макрос QAXAGG_IUNKNOWN в определении вашего класса. Если вы реализовали функции IUnknown вручную, делегируйте вызовы указателю на интерфейс, возвращаемому функцией QAxAggregated::controllingUnknown(), например
HRESULT AxImpl::QueryInterface(REFIID iid, void **iface) { return controllingUnknown()->QueryInterface(iid, iface); }
Не поддерживайте интерфейс IUnknown самостоятельно в вашей реализации queryInterface().
Реализуйте методы интерфейсов COM и используйте QAxAggregated::object(), если вам нужно сделать вызовы подкласса QObject, реализуя элемент управления.
В вашем подклассе QAxBindable, реализуйте QAxBindable::createAggregate() чтобы вернуть новый объект подкласса QAxAggregated.
class MyActiveX : public QWidget, public QAxBindable { Q_OBJECT public: MyActiveX(QWidget *parent); QAxAggregated *createAggregate() { return new AxImpl(); } };
The QAxContainer module is not covered by the GNU General Public License (GPL), the GNU Lesser General Public License (LGPL), or the Qt Commercial License. Instead, it is distributed under the following license.
Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
All rights reserved.
Contact: Nokia Corporation (qt-info@nokia.com)
You may use this file under the terms of the BSD license as follows:
"Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
Смотрите также Каркас ActiveQt.
[Предыдущая: Модуль QAxContainer] [Модули Qt] [Следующая: Модуль QtDBus]
Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies) | Торговые марки | Qt 4.5.3 |
Попытка перевода Qt документации. Если есть желание присоединиться, или если есть замечания или пожелания, то заходите на форум: Перевод Qt документации на русский язык... Люди внесшие вклад в перевод: Команда переводчиков |