QT 4: программирование GUI на С++
Шрифт:
Затем мы вызываем функцию setSizePolicy, чтобы элемент управления ActiveX мог занять все имеющееся в менеджере компоновки пространство, и мы подсоединяем три события ActiveX компонента СОМ к трем слотам.
Остальная часть конструктора PlayerWindow следует обычному образцу, за исключением того, что мы подсоединяем некоторые сигналы Qt
Функция timerEvent вызывается через определенные интервалы времени во время проигрывания мультимедийного клипа. Мы используем ее для продвижения ползунка. Это делается путем вызова функции property для элемента управления ActiveX, чтобы получить значение свойства CurrentPosition (текущая позиция) в виде объекта типа QVariant и вызова функции toDouble для преобразования его в тип double. Мы затем вызываем функцию onPositionChange для обновления положения ползунка.
Мы не будем рассматривать остальную часть программного кода, поскольку большая часть его не имеет непосредственного отношения к ActiveX и не содержит ничего такого, что мы уже не обсуждали ранее. Данный программный код имеется на компакт-диске.
В файле .pro нам необходимо задать элемент для связи с модулем QAxContainer.
При работе с объектами СОМ одной из часто возникающих потребностей является необходимость непосредственного вызова метода СОМ (вместо подсоединения его к сигналу Qt). Наиболее просто это сделать путем вызова функции QAxBase::dynamicCall с указанием имени и сигнатуры метода в первом параметре и аргументов метода в дополнительных параметрах. Например:
Функция dynamicCall принимает до восьми параметров типа QVariant и возвращает объект типа QVariant. Если нам необходимо передавать таким образом IDispatch * или IUnknown *, мы можем инкапсулировать компонент в QAxObject и вызвать для него функцию asVariant для преобразования его в тип QVariant. Если нам необходимо вызвать метод СОМ, который возвращает IDispatch * или IUnknown *, или если нам необходимо осуществлять доступ к свойству СОМ одного из этих типов, мы можем вместо этого использовать функцию querySubObject:
Если мы собираемся вызывать методы, которые имеют неподдерживаемые типы данных в их списке параметров, мы можем использовать QAxBase::queryInterface для
получения интерфейса СОМ и непосредственного вызова метода. Мы должны вызвать функцию Release после завершения использования интерфейса, что является обычным при работе с СОМ. Если нам приходится часто вызывать такие методы, мы можем создать подкласс QAxObject или QAxWidget и обеспечить функции—члены, которые инкапсулируют вызовы интерфейса СОМ. Однако убедитесь, что подклассы QAxObject и QAxWidget не могут определять свои собственные свойства, сигналы и слоты.Теперь мы рассмотрим модуль QAxServer. Этот модуль позволяет нам превратить стандартную программу Qt в сервер ActiveX. Сервер может быть как совместно используемой библиотекой, так и автономным приложением. Серверы в виде совместно используемых библиотек часто называют внутрипроцессными серверами (in-process servers), а автономные приложения — внепроцессными серверами (out-of-process servers).
Наш первый пример QAxServer является внутрипроцессным сервером, отображающим виджет с шариком, который может прыгать вправо и влево. Мы рассмотрим также способы встраивания этого виджета в Internet Explorer.
Рис. 20.6. Виджет AxBouncer в Internet Explorer.
Ниже приводится начало определения класса виджета AxBouncer:
AxBouncer наследует как QWidget, так и QAxBindable. Класс QAxBindable обеспечивает интерфейс между виджетом и клиентом ActiveX. Любой QWidget может быть экспортирован как элемент управления ActiveX, но путем создания подкласса QAxBindable мы можем уведомлять клиента об изменениях значения свойства и peализовывать интерфейсы СОМ в дополнение к уже реализованным при помощи QAxServer.
Если при использовании множественного наследования имеются классы, производные от QObject, мы должны всегда располагать производные от QObject классы первыми для того, чтобы компилятор moc мог их извлечь.
Мы объявляем три свойства для чтения и записи и одно свойство только для чтения. Макрос Q_ENUMS необходим для указания компилятору moc на то, что SpeedValue имеет тип enum (перечисление). Это перечисление объявляется в открытой секции класса: