Visual C++. Создание элемента управления ActiveX
Страница 5. Добавление нового свойства


 

Добавление нового свойства

Как и любой объект, OLE-элемент управления имеет свои методы и свойства. Однако не все они видимы в контейнере. Чтобы стать видимым, они должны быть созданы средством ClassWizad при вызове его вкладки OLE Automation. Видимые свойства и методы контейнер использует для связи с элементом. Используя доступ к свойствам элемента, можно организовать передачу данных между контейнером и элементом управления. Вызывая в контейнере методы элемента, можно организовать обработку этих данных. Это означает по существу реализацию OLE Automation для элементов управления.

Типы свойств

Свойства (properties) определяют внешний вид и поведение элемента управления. У всех свойств есть следующие атрибуты:

  • Имя - это читабельное имя, доступное внешнему миру. Контроллеры автоматизации используют имена для доступа и их модификации.
  • Тип - у всех свойств есть связанные с ними типы данных. Так как свойства доступны внешнему миру посредством механизма OLE-автоматизации, то их типы ограничиваются набором типов OLE, рассматриваемых ниже.
  • Значение - каждое свойство имеет определенное значение заданного типа.
  • Идентификаторы диспетчеризации (DISPID) - у всех элементов автоматизации, то есть свойств, методов и событий, есть числовые идентификаторы (GUID), под которыми они известны системе. Об установлении соответствия между именами свойств и их DISPID заботится класс ColeControl, реализуя интерфейс IDispatch.
  • Символьная константа - обычно с идентификатором каждого свойства элемента управления связана символьная константа. Вместо доступа к свойствам по их именам и идентификаторам, клиенты могут использовать символьные константы.

Элемент управления может предоставлять свои свойства непосредственно по имени либо с помощью специальных методов чтения/записи, называемых методами свойств (properties methods).

С точки зрения реализации, свойства являются элементами класса C++, определенными в классе реализации элемента управления. Клиенты получают доступ к свойствам по имени, идентификатору DISPID или символьной константе. В элементе управления OLE свойство реализуется либо с использованием элемента класса и метода оповещения (notification method), либо с помощью пары методов - чтения/записи (методов Get/Set).

Свойства бывают следующих типов: базовые (stock), внешние (ambient), расширенные (extended) и пользовательские (custom).

Базовыми называются свойства, определенные фирмой Microsoft. Это набор характеристик, которые обычно свойственны всем элементам управления независимо от их типа и выполняемых функций (например, цвет фона). Следует отметить, что элемент управления не обязан поддерживать базовые свойства. Любой элемент, который хочет реализовать базовые свойства, может использовать для доступа к ним стандартные имена и DISPID, определенные фирмой Microsoft, а также методы чтения/записи класса COleControl (например, GetBackColor и SetBackColor ). Эти методы могут быть вызваны как из самого элемента управления, так из внешнего объекта с помощью средств автоматизации.

В классе COleControl есть несколько специальных методов, сообщающих элементу об изменении его базовых свойств ( OnBackColorChanged, OnBorderStylerChanged, OnEnabledChanged, OnFontChanged,OnForeColorChanged, OnTextChanged ). Данные методы объявлены виртуальными, поэтому их можно спокойно изменять. Это следует делать в том случае, если элементу необходимо отслеживать изменения базовых свойств и реагировать на них.

Внешние свойства представляют собой стандартный набор свойств, доступных только для чтения и реализованных во всех контейнерах. Они предоставляют элементу управления информацию о его окружении, т.е. о контейнере. Элементы управления могут использовать эту информацию для согласования своего визуального представления в соответствии с интерфейсом контейнера. Для чтения внешних свойств контейнера используются методы, реализованные в классе COleControl и имеющие префикс Ambient...(). Необходимо отметить, что внешние свойства реализуются контейнером, а элемент только считывает их. Нужно добавить, что контейнеры не обязаны реализовывать такие свойства.

Расширенными свойствами называются такие свойства, которые контейнер связывает с каждым конкретным элементом управления. Обратим внимание на то, что контейнер сам несет ответственность за эти свойства и “подключает” их к каждому элементу по своему усмотрению. Для того, чтобы контейнер мог связать расширенные свойства с элементом управления, он во время встраивания элемента создает небольшой вспомогательный объект, называемый расширенным элементом управления. Посредством механизма агрегации этот объект принимает все вызовы методов свойств элемента управления, что позволяет ему обрабатывать их прежде, чем они попадут к реальному элементу. По существу, расширенный элемент управления является внешней оболочкой элемента управления OLE.

Пользовательскими называются свойства, которые определены разработчиком OCX-объекта. Пользовательские свойства применяются для придания отличительных черт элементу управления. Каждому пользовательскому свойству необходимо присвоить уникальное имя и DISPID. Кроме того, следует убедиться что это свойство имеет один из типов OLE.

Добавление свойств

В процессе проектирования OCX-объекта можно добавлять два вида свойств: базовые и пользовательские. Несколько базовых свойств (другое название - стандартные свойства) определены и поддерживаются в базовом классе COleControl. Это общие свойства, пригодные для большинства проектируемых OLE-элементов управления: Appearance - внешний вид (например, 3-мерный или плоский); BackColor - цвет фона; BorderStyle - тиль рамки; Caption - заголовок элемента; Enabled - состояние доступен/недоступен; Font - шрифт при печати заголовка и других сообщений, связанных с элементом управления; ForeColor - цвет переднего плана; hWnd - маркер (дескриптор) окна; ReadyState - состояние готовности; Text - текст, другое название свойства Caption.

Наряду с базовыми свойствами можно задать новое свойство, соответствующее специфике проектируемого элемента, не определенное в базовом классе. Возможны четыре способа реализации добавляемого свойства:

Member Variable - реализация свойства предполагает введение в созданный класс элемента управления переменной, видимой в контейнере. Это простейший способ реализации. Однако чаще применяются три следующих, когда наряду с переменной создаются и другие элементы класса;

Member Variable With Notification - наряду с переменной создается специальная функция уведомления. Она автоматически вызывается в каркасе приложения всякий раз при изменении значения свойства, что позволяет элементу управления должным образом отреагировать на изменение своего свойства - например, организовать свою перерисовку;

Set/Get Methods - предполагает защищенный доступ к переменной класса, задающей свойство. Хотя сама переменная будет не видима в контейнере, здесь будут доступны автоматически построенные методы Get и Set . Первый позволяет прочитать значение, второй - задать новое значение свойства. Кроме защищенности свойства, этот способ удобен тем, что позволяет организовывать дополнительные вычисления, например, в методе Set можно произвести проверку, разрещающую или запрещающую изменение свойств;

Parameterized - параметризированная реализация применяется, когда переменная класса должна быть массивом и свойство задается не единственным скалярным значением, а совокупностью значений. Эта реализация предполагает построение методов Get и Set. Автоматически эти методы создаются с параметром, включающим индексы элемента массива.

Все свойства имеют определенный тип. Так как OLE не является частью языка Visual C++, то типы OLE отличаются от привычных типов C++. Рассмотрим основные типы OLE: BSTR - строка, каждый символ которой занимает 2 байта; I2 - целое длиной 2 байта; I4 - целое длиной 4 байта; UI4 - целое без знака длиной 4 байта; R4 - вещественное с плавающей точкой длиной 4 байта; R8 - вещественное с плавающей точкой длиной 8 байта; BOOL - булевское значение (целое длиной 2 байта); VARIANT - для переменных, тип значений которых может варьироваться; PTR - указатель на объект; OLE_COLOR - тип (UI4), введенный для переменных, задающих цвет.

Тип свойства выбирается из списка “Type” при добавлении нового свойства при помощи средства ClassWizard. В этом списке, как правило, указываются не типы OLE, а совместимые с ними типы, например тип short, который автоматически транслируется в тип I2. Однако в списке “Type” есть и OLE-типы, например, типы BSTR и OLE_COLOR.

Процедура добавления свойства

Для этого необходимо вызвать ClassWizard и выбрать вкладку OLE Autonation, а затем:

  • В поле “Class name” необходимо выбрать имя класса элемента управления, производного от COleControl. Напомним, что производные классы наследуют от базового класса его данные и методы. Так все OLE-элементы управления могут использовать открытые для них методы базового класса COleControl.
  • При помощи кнопки “Add Property” вызвать диалоговое окно для добавления свойств.
  • Для пользовательских свойств в окно комбинированного списка “External Name” ввести его имя, а для базовых - выбрать имя из этого списка.
  • В группе “Implementation” для пользовательских свойств включить один из переключателей: “Member Variable” или “Get/Set”. Для базового свойства будет автоматически выбран переключатель “Stock”. Выбор “Member Variable” задает два первых способа реализации свойства. По умолчанию предлагается второй способ с построением функции уведомления. Если отказаться от нее, то реализуется первый способ. Выбор переключателя “Get/Set” задает третий и четвертый способы реализации свойства. Ввод информации в окне “Parameter List” означает выбор параметризированного свойства, и тогда параметры методов Ge
  • t и Set будут включать индексы элемента массива, задающего свойство.
  • Из списка “Type” следует выбрать тип свойства. Для базовых свойств тип задается автоматически.
  • Задав все характеристики, следует подтвердить создание нового свойства, выбрав кнопку
  • “Ok”.

Действия, выполняемые ClassWizard, при добавлении свойства

Для пользовательского свойства, при добавлении которого был включен переключатель “Member Variable” , ClassWizard вставит в файл CNameCtl.h описание переменной класса и заголовок функции уведомления (если не было отказа). Созданная переменная, кстати, будет видима в контейнере, который будет содержать OLE-элемент управления. Остов функции уведомления создается и вставляется в файл CNameCtl.cpp. Тело функции содержит единственный вызов SetModif iedFlag().

Когда контейнер сохраняет свое состояние, сохраняется и свойство встроенного OLE-элемента управления. Поэтому всякий раз, когда меняется свойство, необходимо включить флаг модификации состояния документа. Это и делает функция уведомления. Все остальные возможные действия, связанные с изменением состояния, программист должен добавить сам.

Для пользовательского свойства, при добавлении которого был включен переключатель “Get/Set methods” , ClassWizard создаст и добавит в h- и cpp-файлы заголовки и остовы этих методов. В процессе добавления свойств можно отказаться от одного из этих методов, и тогда свойство будет предназначаться “только для чтения” или “только для записи”.

Хотя ClassWizard создает остовы методов Get и Set, пользоваться ими без доработки нельзя, так как он не создает переменной класса. Ее нужно добавить вручную и соответственно откорректировать тела методов. Следует заметить, что сама переменная не будет видима в контейнере - она скрыта от него, доступны лишь методы Get и Set.

Следующая важная часть работы ClassWizard - формирование раздела DISPATCH_MAP (раздела схемы диспетчеризации) в файле NameCtl.cpp. Для каждого пользовательского или базового свойства добавляется соответствующий макрос. Для базовых свойств добавляется один из макросов с префиксом DISP_STOCKPROP_ в соответствии с задаваемым базовым свойством. Для пользовательских свойств добавляемый макрос зависит от способа реализации свойства. Каждому из четырех способов реализации соответствует свой макрос: DISP_PROPERTY(), DISP _ PROPERTY_NOTIFY(), DISP_PROPERTY_EX(), DISP_PROPERTY_PARAM(). Параметрами макросов являются имя класса и свойства, тип свойства, и, в зависимости от типа макроса, имена переменной класса и функции уведомления или имена Get и Set методов.

С каждым свойством ClassWizard связывает идентификатор диспетчеризации ID и добавляет информацию о нем в файл Name.odl.

“Постоянные” свойства и их инициализация

В классе CNameCtrl построен остов метода DoDropExchange - аналог метода DoDataExchange класса диалоговых окон. Этот метод вызывается всякий раз, когда OLE-элемент управления создается, читается или записывается в файл на диск. В ее тело для каждого свойства можно добавить вызов метода с префиксом PX (Propertiy eXchange) - аналог DDX-метода.

Свойство, для которого добавлен вызов PX-метода, называется постоянным (persistent). PX-метод позволяет задать значение постоянного свойства по умолчанию. Для каждого типа свойства применяется свой PX-метод.

 
« Предыдущая статья   Следующая статья »