Расширение свойств элементов управления ActiveX средствами ATL

Технология Active Template Library. Создание полнофункционального элемента управления и расширение свойств. Подготовка рабочего пространства и ресурсов. Проектирование пользовательского интерфейса. Добавление переменных для управления анимацией.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 09.12.2015
Размер файла 722,5 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru/

[Введите текст]

МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РФ

ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ

ВЫСШЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ

«ВОРОНЕЖСКИЙ ГОСУДАРСТВЕННЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ»

(ФГБОУ ВПО «ВГТУ»)

Информационных технологий и компьютерной безопасности (факультет)

Кафедра систем информационной безопасности

КУРСОВАЯ РАБОТА

по дисциплине «Безопасность сетей ЭВМ»

Тема: «Расширение свойств элементов управления ActiveX средствами ATL»

Воронеж

2014

Введение

Общая характеристика работы

Актуальность

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

Определение стандартов для программных компонентов и является актуальной задачей спецификации управляющих элементов ActiveX (ActiveX Controls). Путем установления стандартных интерфейсов, способных поддерживать СОМ-объекты для выполнения определенных действий, спецификация управляющих элементов ActiveX предоставляет общую схему построения мощных компонентов. А так как компонентам нужен способ эффективного взаимодействия с использующим их кодом, то спецификация управляющих элементов ActiveX определяет и правила создания контейнеров управляющих элементов (control containers) клиентских программ, знающих как работать с этими элементами.

Так как управляющие элементы ActiveX используются практически во всем программном обеспечении, то изучение и расширение свойств этих элементов становится очень актуальной задачей.

Цель и задачи

Цель данной работы заключает в расширении свойств элементов управления ActiveX средствами ATL.

В достижении поставленной цели нужно решить некоторые задачи:

Изучить управляющие элементы ActiveX;

Изучить технологию ATL;

Создать элемент управления ActiveX средствами ATL;

Расширить свойства созданного элемента ActiveX.

1. Технология ActiveX

Технология ActiveX базируется на технологии Microsoft COM (Component Object Model - модель компонентных объектов), позволяющей создавать и использовать программные компоненты, предоставляющие различные сервисы другим приложениям, компонентам и операционной системе. COM представляет собой одну из реализаций концепции распределенных вычислений, базирующейся в общем случае на предоставлении возможности приложениям использовать для расширения своей функциональности готовые компоненты и объекты (иногда они называются сервисами). Технология COM позволяет использовать объектно-ориентированный подход не в рамках одного приложения, а в рамках операционной системы, но, в отличие от стандартных классов, определенных в исходном тексте и реализуемых как объекты в адресном пространстве одного процесса, эти компоненты могут в общем случае располагаться в адресных пространствах разных процессов и даже на разных компьютерах.

Использование COM, и, в частности, технологии ActiveX, позволяет обеспечить создание приложений, собираемых из готовых компонентов - элементов управления ActiveX, отличающееся от привычной пользователям C++Builder или Delphi разработки приложений с помощью VCL-компонентов тем, что такая "сборка" не зависит от того, на каком языке написаны как готовые компоненты, так и использующее их приложение - лишь бы средство разработки поддерживало возможность использования таких компонентов в разрабатываемом приложении (такое приложение обычно называется контейнером).

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

Как любой COM-сервер, элемент управления ActiveX обладает уникальным идентификатором GUID и должен быть зарегистрирован в реестре. На основании этой записи может быть осуществлен поиск местоположения файла с расширением *.ocx, содержащего его реализацию.

Таким образом, создав элемент управления ActiveX, обладающий интересующей Вас функциональностью, Вы можете в дальнейшем позволить его пользователям встраивать этот элемент в свои приложения (например, написанные на Visual Basic, PowerBuilder, Delphi, C++Builder и др.), отображать его в web-браузере в составе выгруженной с Вашего web-сервера HTML-страницы, включать его в состав документов MS Office, при этом Вы не обязаны предоставлять исходный текст этого компонента.

1.1 Технология Active Template Library (ATL)

Библиотека активных шаблонов (ATL) представляет собой основу для создания небольших СОМ-компонентов. В ATL использованы новые возможности шаблонов, добавленные в C++. Исходные тексты этой библиотеки поставляются в составе системы разработки Visual C++. Кроме того, в эту систему разработки введено множество мастеров Visual C++, что облегчает начальный этап создания ATL-проектов.

Библиотека ATL обеспечивает реализацию ключевых возможностей СОМ компонентов. Выполнения многих рутинных процедур можно избежать за счет использования классов шаблонов ATL. Приведем некоторые функций ATL:

Утилита AppWizard, предназначенная для создания первичного ATL-проекта;

Мастер объектов, используемый для добавления в проект компонентов различных типов;

Поддержка по умолчанию основных интерфейсов COM, таких как IUnknown и IClassFactory;

Поддержка механизма транспортировки пользовательского интерфейса;

Поддержка базового механизма диспетчеризации (автоматизации) и двунаправленного интерфейса;

Существенная поддержка разработки небольших элементов управления ActiveX.

1.2 Создание полнофункционального элемента управления АсtivеХ средствами АTL и расширение свойств

Итак, мы узнали, что элемент управления АсtivеХ -- это графический объект СОМ, который может иметь набор связанных с ним страниц свойств. Однако важно отметить, что некоторые элементы управления невидимы во время выполнения приложения. При этом они являются графическими "строительными" компонентами во время проектирования.

Элемент управления будет поддерживать точки соединения, свойства и методы, оконные элементы. Кроме того, мы познакомитесь с основами анимации, поскольку наш элемент будет способен прокручивать несколько изображений.

Подготовка рабочего пространства и ресурсов

Создадим новый внутрипроцессный сервер с именем АхСаrServer с помощью мастера АТL АррWizard, оставив без изменения установки по умолчанию.

Рисунок 1 - Создание проекта

Рисунок 2 - Свойства проекта

Вставим элемент Full Control, используя мастер ATL Object Wizard.

Рисунок 3 - Вставка элемента Full Control

На вкладке Names введём АхСаr в поле Short name, а остальные имена оставим как есть.

Рисунок 4 - Свойства элемента Full Control

На вкладке Miscellaneous отметим флажки Insertable и Windowed Only (рис. 5). Эти опции позволяют элементу управления поддерживать свое собственное окно и внедряться в контейнеры документов ОLЕ.

Рисунок 5 - Расширение свойств элемента Full Control

Наш элемент управления будет демонстрировать анимацию путем отображения нескольких битовых массивов в зависимости от параметров состояния автомобиля.

Используя редактор ресурсов Visual Studio, вставим пять битовых массивов (Insert Resource). Чтобы это осуществить, щелкним на ресурсе битового массива в папке Вitmap панели ResourceView и выберите Рroperties.

Рисунок 6 - Тип ресурса

Рисунок 7 - Элемент анимации №1

Рисунок 8 - Элемент анимации №2

Рисунок 9 - Элемент анимации №3

Рисунок 10 - Элемент анимации №4

Рисунок 11 - Элемент анимации №5

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

2. Проектирование пользовательского интерфейса

Учитывая, что элементы управления АсtivеХ могут использоваться клиентами только через интерфейс диспетчеризации, наш элемент управления должен экспортировать все свои функциональные возможности через единственный [default]-интерфейс. Мы добавим в IАхСаr следующие методы: SpeedUp(), CreateCar () И AboutBox (), а также свойства: Animate, Speed, MaxSpeed и PetName.. Идентификаторы DISPID пользовательских элементов могут быть оставлены в своих значениях по умолчанию, однако не забудем установить предопределенное значение DISPID _ABOUTBOX для AboutBox (). Чтобы наиболее полно интегрироваться в контейнер на этапе проектирования, свойство Animate будет использовать специальное перечисление. Вот код IDL

// Специальное перечисление, используемое для анимации

//

[uuid(8FB31CFO-7490-11d3-B92E-0020781238D4), vl_enum]

typedef enum AnimVal

{

[helpstring("Animate")] Yes 1,

[helpstring("Don't Animate")] No 0

}

AnimVal;

[object, uuid(65AOEEBF-745F-I1D3-B92E-0020781238D4), dual,

helpstring("IAxCar Interface"),pointer_default(unique)

interface IAxCar: IDispatch

{

[id (1), helpstring ("Add 10 to current speed")]

HRESULT SpeedUp();

[id(2), helpstring("Set the name and max speed of the car")]

HRESULT CreateCar([in] BSTR petName, [in] short maxSp);

[propget, id(3), helpstring("Should I animate?")]

HRESULT Animate(rout, retval] AnimVal *newVal);

[proPPu1:, id(3), helpstring("Should I animate?")]

HRESULT Animate ([in] AnimVal newVal);

[propget, id(4), helpstring("The max speed")]

HRESULT MaxSpeed([out, retval] short *pVal);

[propput, id (4), helpstring ("The max speed")]

HRESULT MaxSpeed([in] short newVal);

[propget, id(S), helpstring("Car's pet name")]

HRESULT PetName([out, retval] BSTR *pVal);

[propput, id(5), helpstring("Car's pet name")]

HRESULT PetName([in] BSTR newVal);

[propget, id(6}, helpstring("Current speed")]

HRESULT Speed([out, retval] short *pVal};

[propput, id (6), helpstring ("Current speed")]

HRESULT Speed([in] short newVal);

[id(DISPID_ABOUTBOX), helpstring ("About AxCars")]

HRESULT AboutBox();

};

2.1 Реализация пользовательских свойств

Класс САхСаг для реализации пользовательских свойств требует следующие переменные-члены. Добавим их в закрытый сектор и присвоим значения по умолчанию в конструкторе:

// Закрытые переменные-члены класса СAxCar

//

short rn_maxSpeed;

CComBSTR m bstrPetName;

AnimVal m bAnirnate;

short m_currSpeed;

// Constructor

//

CAxCar ()

{

m_bWindowOnly = TRUE;

m _ maxSpeed = 0;

m_bstrPetName = L"";

m_currSpeed = 0;

m_bAnirnate = No;

}

Реализация методов СreateCar() и AboutBox()

Реализация метода CreateCar() также не составляет проблемы: присвоим внутренним переменным значения входящих параметров. Хотя мы демонстрируем каждую переменную как пользовательское свойство, данный метод позволяет клиенту установить состояние при создании элемента управления за один вызов:

// Устанавливаем параметры состояния

//

STDMETHODIMP CAxCar::CreateCar(BSTR petName, short rnaxSp)

{

rn_maxSpeed = rnaxSp;

m bstrPetName = petName;

return S_OK;

}

Что касается метода AboutBox (), то сначала создадим новый диалоговый ресурс. Мы используем для отображения диалога шаблон CSirnpleDialog<>.

Имея ресурс диалога, реализуем метод AboutBox ():

STDMETHODIMP CAxCar::AboutBox()

{

CSirnpleDialog<IDD_ABOUTBOX> d;

d.DoModal();

return S_OK;

}

Поскольку мы присвоили методу DISPID_ABOUTBOX, конечный пользователь может запустить AboutBox() из IDE.

Сборка [default, source]-интерфейса

Кокласс САхСаr способен генерировать два события для контейнера. Первое событие посылается, когда машина "собирается" взорваться. Второе событие отправляется, когда машина уже взрывается. Добавим нижеследующие методы к нашим [default, source] -интерфейсу диспетчеризации:

[uuid(65AOEECl-745F-IID3-B92E-0020781238D4),

helpstring("_IAxCarEvents Interface")]

dispinterface IAxCarEvents

{

properties:

methods:

[id(l), helpstring("rnethod BlewUp")] HRESULT BlewUp();

[id(2}, helpstring("rnethod AboutToBlow")] HRESULT AboutToBlow();

};

Теперь сформируем прокси-класс точек соединения с помощью мастера Inlplenlent Connection Point Wizard после того, как перекомпилируем свой IDL-файл.

BEGIN_CONNECTION_POINT_MAP(CAxCar)

CONNECTION_POINT_ENTRY (IID_IPropertyNotifySink)

CONNECTION_POINT_ENTRY (DIID__IAxCarEvents)

END_CONNECTION_POINT_MAP()

2.2 Добавление переменных для управления анимацией

Теперь, когда мы сформировали базовую инфраструктуру СахСаг, сосредоточимся на командах, отвечающих за отображение битовых массивов в цикле анимации. Для начала добавим еще несколько переменных в закрытый сектор нашего класса и определим массив элементов типа HBITMAP для хранения битовых изображений, которые мы нарисовали в первом шаге работы. Также нам нужна переменная, идентифицирующая текущий кадр анимации. Мы собираемся прокручивать от трех до пяти изображений в одном цикле. Если скорость машины существенно ниже максимально допустимой, то отображаем три картинки. Если собираемся взорваться, то четыре. Если уже разлетелись на куски, то рисуем все пять. Определим еще несколько вспомогательных констант. Итак, добавим в заголовочный файл СахСаг следующее:

// Несколько вспомогательных констант

//

const int MAX IMAGES = 5;

const int MAX NORMAL = 3;

const int ABOUT TO BLOW = 4;

const int BLOWN UP = 5;

Вот также полный набор закрытых переменных для класса:

short m_maxSpeed; // Максимальная скорость машины

CComBSTR m bstrPetName; // Имя машины

short m_currSpeed; // Текущая скорость машины

HBITMAP m_carlmage[MAX_lMAGES]; // Массив битовых изображений

AnimVal m bAnimate; // Флаг анимации (Yes или No)

short m_currlmage; // Текущее изображение в массиве

short m_currMaxFrames; // Число кадров в цикле анимации

Теперь заполним массив типов HBITMAP идентификаторами ресурсов битовых изображений. Для корректной работы цикла анимации очень важно, чтобы численные значения идентификаторов ресурсов битовых массивов шли по порядку.

// Файл <resource.h> должен нумеровать ресурсы по порядку

//

#define IDB_LEMON1 201

#define IDB_LEMON2 202

#define IDB_LEMON3 203

#define IDB_ ALMOSTBLOWNUP 204

#define IDB_ BLOWNUP 205

Переопределим метод FinalConstruct() в классе САхСаг и загрузим изображения с помощью вызова АРI LoadBitmap (). Первый параметр этой функции -- HINSTANCE элемента управления, который может быть получен из глобальной переменной CComModule. Мы используем IDB_LEMON1 (идентификатор ресурса первого битового массива) в качестве точки отсчета:

// Загружаем все битовые массивы

//

HRESULT FinalConstruct()

{

for(int i = 0; i < MAX IGES; i++)

{

m_carlmage[i] = LoadBitrnap(_Module.m_hInst, MAKEINTRESOURCE(IDB LEMONl + i));

}

return S OK;

}

Затем переопределим метод FinalRelease (), чтобы освобождать определители битовых массивов, используя DeleteObject():

// Освобождаем ресурсы

//

void FinalRelease()

{

for(int i = 0; i < MAX_IMAGES: i++)

DeleteObject(m_carlmage[i]);

}

Оставшиеся переменные-члены (m_currMaxFrames и m_currImage) могут быть установлены в конструкторе следующим образом:

// Устанавливаем новые параметры состояния

//

САхСаг()

{

m_bWindowOnly = TRUE;

m _ maxSpeed = 0;

m bstrPetName = L'll';

In_currSpeed = 0;

In bAnimate = No;

m _ currImage = 0;

m currMaxFrarnes MAX NORMAL;

}

2.3 Конфигурирование таймера

Чтобы прокручивать в цикле битовые изображения, нам потребуется способ передвижения кадра. В данной работе мы будем менять кадр из обработчика сообщения WM_TIMER. Используйте мастер Add Windows Message Handler Wizard для направления сообщения WM_TIMER на класс САхСаг. Мастер модифицирует карту сообщений и добавит пустой код для метода OnTimer(). В реализации метода увеличиваем на 1 номер кадра и проверяем достижение верхнего предела числа кадров (от трех до пяти в зависимости от скорости машины). При смене кадра перерисовываем изображение с помощью FireViewChange():

//

LRESULT CAxCar::OnTimer(UINT uMsg, WPARAM wparam, LPARAM lParam, BOOL& bHandled)

{

m_currImage = m_currImage + 1;

if(m_currImage >= m_currMaxFrames)

m_currImage = 0;

FireViewChange();

return 0;

}

Теперь запустим таймер окна. Вернёмся к реализации свойства Animate и добавим вызовы SetTimer() или KillTimer() в зависимости от значения параметра AnimVal. Тем самым конечный пользователь получит возможность запускать и прекращать анимационный цикл посредством свойства СОМ:

// Создаем или прекращаем таймер

//

STDMETHODIMP CAxCar::put Animate (AnimVal newVal)

{

m bAnimate = newVal;

if(::IsWindow(rn_hWnd) && (m_bAnimate -- Yes))

SetTimer(l, 250);

else if(::IsWindow(m_hWnd))

KillTimer(l);

return S_OK;

}

Последний шаг, который необходимо выполнить перед отображением битовых массивов в OnDraw(), -- это установить текущую верхнюю границу числа кадров. Проделаем это в методе SpeedUp(). После модификации переменной m_currMaxFrames посылаем наши события:

// Устанавливаем верхнюю границу числа кадров и посылает событие

//

STOMETHOOIMP CAxCar::SpeedUp()

{

m_currSpeed += 5;

if((m_maxSpeed - m_currSpeed) <= 10)

{

Fire AboutToBlow();

m currMaxFrames = ABOUT TO BLOW;

}

if(m_currSpeed >= m_maxSpeed)

{

m_currSpeed = m_maxSpeed;

Fire_BlewUp();

m currMaxFrames BLOWN UP;

return S_OK;

}

Рисуем изображения

Теперь все стоит на своих местах. Осталось только отобразить нужный битовый массив в реализации OnOraw():

//

HRESULT CAxCar::OnOraw(ATL ORAWINFO& di)

{

RECT& rc = * (RECT*)di.prcBounds;

Rectangle (di.hdcOraw, rc.left, rc.top, rc.right, rc.bottom);

BITMAP bmInfo;

HBITMAP oldBitmap;

HBITMAP newBitmap;

HOC memOC;

SIZE size;

GetObject(m_carlmage[rn currImage], sizeof(brnlnfo), &brnInfo);

size.cx = bmlnfo.bmWidth;

size.cy = bmInfo.brnHeight;

newBitrnap = rn_carImage[m_currImage];

memDC = CreateCompatibleDC(di.hdcDraw);

oldBitmap = (HBITMAP}SelectObject(rnernDC, newBitmap);

StretchBlt(di.hdeDraw, re.left, re.top, re.right, rc.bottom,

merrC, 0, 0, size. ex, size.cy, SRCCOPY);

SeleetObject(di.hdeDraw, oldBitmap);

DeleteDC(memDC);

return S_OK;

}

Для запуска или прекращения анимации используется свойство Animate. Внутри программы это приводит к созданию или удалению ресурса таймера. Обработчик сообщения WM_TIMER отвечает за сдвиг текущего кадра и не превышение верхнего предела числа кадров. Этот верхний предел хранится в переменной m_ currMaxFrames и устанавливаемый в методе SpeedUp ().

2.4 Расширение специальных свойств

СОМ предоставляет особый интерфейс с именем IPropertyNotifySink, который дает возможность контейнеру принимать или не принимать новые установки свойств, а также информирует контейнер об изменении свойства. В файле IDL соответствующие свойства должны быть отмечены атрибутами [requestedit] и/или [bindable].

Вставим в IDL-файл нужный атрибут для каждого из свойств [default]-интерфейса IАхСаг:

// Связываем свойства с приемником свойств клиента

//

[object, uuid(65AOEEBF-745F-IID3-B92E-0020781238D4), dual,

helpstring("IAxCar Interface") ,pointer default (unique)

interface IAxCar: IDispatch;

{

[id(1), helpstring("Add 5 to current speed")]

HRESULT SpeedUp();

[id(2), helpstring("Set the name and max speed of the car")]

HRESULT CreateCar([in] BSTR petName, [in] short maxSp);

[propget, id(3), helpstring("Should I animate?"), bindable, requestedit]

HRESULT Animate([out, retval] AnimVal *newVal);

[propput, id(3), helpstring("Should I animate?"), bindable, requestedit]

HRESULT Animate([in] AnimVal newVal);

[propget, id(4), helpstring("The max speed"), bindable, requestedit]

HRESULT MaxSpeed([out, retval] short *pVal);

[propput, id(4), helpstring("The max speed"), bindable, requestedit]

HRESULT MaxSpeed([in] short newVal);

[propget, id(5), helpstring("Car's pet name"), bindable, requestedit]

HRESULT PetName([out, retval] BSTR *pVal);

[propput, id(5), helpstring("Car's pet name"), bindable, requestedit]

HRESULT PetName([in] BSTR newVal);

[propget, id(6), helpstring("Current speed"), bindable, requestedit]

HRESULT Speed([out, retval] short *pVal);

[propput, id(6), helpstring("Current speed"), bindable, requestedit]

HRESULT Speed([in] short newVal);

[id(DISPID_ABOUTBOX), helpstring("About AxCars")]

HRESULT AboutBox();

};

После того как свойства исправлены, перепишем методы [propput] под использование FireOnEditRequest() и FireOnChanged(). Вот модифицированная реализация для свойства Animate:

//

STDMETHODIMP CAxCar::put_Animate(AnimVal newVal)

{

if(FAILED(FireOnRequestEdit(3))} II [id(3)] = Animate

return S FALSE;

m bAnimate = newVal;

if(::IsWindow(m_hWnd) && (m_bAnimate == Yes))

SetTimer(l, 500);

else if(::IsWindow(m_hWnd)

KillTimer(l);

FireOnChanged(3); //[id(3}] = Animate

return S_OK;

}

Параметр, передаваемый в методы FireOnRequestEdit () и FireOnChanged(), -- это DISPID вашего специального свойства (т. е. атрибут [id] в IDL-определении).

2.5 Поддержка постоянства свойств

Здесь нам понадобится сделать некоторые изменения, чтобы контейнер помнил значения наших специальных свойств и между сеансами работы. АТL предоставляет автоматическую поддержку постоянства свойств на основе моделей потока байтов и объектов хранения, используя шаблоны IPersistStoragelrnpl<> и IPersistStreamlnitlmpl<>.

Нам предстоит отредактировать методы [propput] и внести в них последнее добавление: когда мы осуществляем новое присвоение внутренней переменной свойства, вызываем SetDirty(), чтобы отметить, что свойство изменилось. Таким образом клиент "понимает", какой именно элемент требуется сохранить. Вот окончательная версия метода put_Animate ():

//

STDMETHODIMP CAxCar::put_Animate(AnimVal newVal)

{

if(FAILED(FireOnRequestEdit(3)))

return S FALSE;

m bAnimate = newVal;

if(::IsWindow(m_hWnd) && (m_bAnimate== Yes))

SetTimer(l, 500);

else if(::IsWindow(m_hWnd))

KillTimer(l);

SetDirty(TRUE);

FireOnChanged(3);

return S_OK;

}

Откроем заголовочный файл класса, найдем карту свойств и исправим ее следующим образом:

//

BEGIN PROP MAP(CAxCar)

PROP_DATA _ENTRY ("_ cx", m _ sizeExtent. cx, VT UI4)

PROP_DATA_ENTRY ("_cy", m_sizeExtent. cy, VT UI4)

PROP_ENTRY ("Animate" , 3, CLSID_NULL)

PROP_ENTRY ("Speed" , 4, ,CLSID_NULL)

PROP_ENTRY ("PetName" , 5, CLSID_NULL)

PROP_ENTRY ("MaxSpeed" , 6, CLSID_NULL)

END_PROP_MAP()

2.6 Создание страницы пользовательских свойств

Позволим пользователю изменять на странице свойств свойства Animate, MaxSpeed И PetName . При создании страницы средствами АТL первым шагом будет вызов мастера ATL Object Wizard и вставка в нем нового объекта типа propertyPage из категории Controls. Используя этот мастер, добавим новую страницу, задав ConfigureCar в качестве ее имени. На вкладке Strings отредактируем поле Title по своему усмотрению.

Чтобы связать элементы GUI с соответствующими свойствами интерфейса IАхСаг, начнём с направления уведомления EN_CHANGE на каждое из полей редактирования, а уведомления BN_CLICKED -- на поле флага, используя мастер Add Windows Message Handler. В реализации обработчиков событий сделаем доступной кнопку Арр1у путем вызова SetDirty():

//

LRESULT OnClickedCheckanim(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)

{

SetDirty (TRUE);

return 0;

}

В методе Арр1у() нам требуется получить значения, содержащиеся в элементах GUI, и передать их соответствующим свойствам выбранных элементов управления. Вспомним, что IProperyPageImpl<> хранит массив указателей IUnknown (m_ppunk), которые соответствуют элементам управления, выбранным в контейнере. Используем этот массив для установки новых значений свойств в объектах. Счетчик выбранных на данный момент элементов управления хранится в переменной-члене m_nObjects. Вот код метода Арр1у():

//

STDMETHOD(Apply) (void)

{

for (UINT i = 0; i < m_nObjects; i++)

{

IAxCar* pCar = NULL;

CComBSTR temp;

GetDlgItemText( IDC_EDITNAME, temp.m_str);

m_ppUnk[i]->QueryInterface(IID_IAxCar, (void**)&pCar)i

pCar->put_PetName(temp);

pCar->put_Animate(

(AnimVal)IsDlgButtonChecked(IDC_CHECKANIM));

pCar->put_MaxSpeed(GetDlgItemInt(IDC_EDITSPEED));

pCar->Release()i

}

m_bDirty = FALSE;

return S_OK;

}

Теперь нужно передать данные "в обратном направлении". Когда пользователь вызывает страницу свойств, хотелось бы, чтобы текущие значения свойств отображались в соответствующих позициях GUI. Обычно эти позиции редактируются в обработчике сообщения WM _INITDIALOG, которое посылается перед тем, как визуализировать диалог. Добавим запись WM _INITDIALOG в карту сообщений, а также следующий код:

LRESULT OnInitDialog(UINT uMsg, WPARAM wparam, LPARAM Iparam,

BOOL& bHandled)

{

USES CONVERSION;

if (m_nObjects > 0)

{

IAxCar* pCar = NULL;

short tpSP;

CComBSTR temp;

m_ppUnk[O]->QueryInterface(IID_IAxCar, (void**)&pCar);

pCar->get_MaxSpeed(&tempSP);

SetDlg1tem1nt(1DC_ED1TSPEED, tempSP);

AnimVal curAnim;

pCar->get_Animate(&curAnim);

CheckDlgButton(1DC_CHECKAN1M, (BOOL)curAnim);

pCar->get_PetName(&temp.m_str);

SetDlg1ternText(1DC_ED1TNAME, W2A(temp.m_str));

pCar->Release();

SetDirty(FALSE);

}

return 0;

}

Вернемся к карте свойств и зададим в пользовательских свойствах применение соответствующей страницы вместо CLS1D_NULL (отсутствие страницы). Мастер ATL Object Wizard уже сгенерировал идентификатор CLSID для новой страницы, который можно найти в самом верху заголовочного файла класса. Используя эту константу, исправим карту свойств следующим образом:

//

BEG1N_PROP_MAP(CAxCar)

PROP_DATA_ENTRY ("_cx", m_sizeExtent. cx, VT U14)

PROP_DATA _ENTRY ("_ cy", m _ sizeExtent. cy, VT U14)

PROP_ENTRY ("Animate", 3, CLSID_ConfigureCar)

PROP_ENTRY ("Speed", 4, CLSID_ConfigureCar)

PROP_ENTRY ("PetName", 5, CLSID_ConfigureCar)

PROP_ENTRY ("MaxSpeed", 6, CLSID _ ConfigureCar)

END PROP MAP ( )

2.7 Тестирование созданного элемента

Теперь можем протестировать нашу новую страницу. Поместим экземпляр модифицированного (и прекомпилированного) элемента управления в проект Visual Basic и запустим:

Рисунок 12 - Установка названия машины и скорости

интерфейс проектирование переменная анимация

Рисунок 13 - Тестирование автомобиля

Рисунок 14 - Предупреждающее сообщение

Рисунок 15 - Взрыв автомобиля

Выводы

В ходе данной курсовой работы был спроектированы элементы управления ActiveX средствами АТL. Все эти элементы используются как графические составные блоки. Чтобы поддерживать дополнительные функциональные возможности, выходящие за рамки простого кокласса, элементы управления реализуют несколько стандартных интерфейсов СОМ, служащих для отображения объектов, обеспечения их постоянства и поддержки страниц свойств. Создание полного элемента управления в АТL начинается с мастера Object Wizard.

Так же был изучено использование моделей постоянства свойств в СОМ и то, каким образом АТL поддерживает эти модели, предоставляя набор шаблонов и карту свойств. Карта свойств в АТL служит также для связывания свойств с соответствующими страницами свойств. Страница свойств -- это еще один класс СОМ, поддерживающий стандартный интерфейс IPropertyPage.. Контейнер обнаруживает страницы, которые работают с коклассом, путем запроса ISpecifyPropertyPages..

В ходе работы был создан и протестирован, с помощью Visual Basic, полнофункциональный элемент управления ActiveX, с возможность расширения базовых свойств.

Список использованных информационных источников

1. Трельсен Э.Модель СОМ и применение ATL3.0: Пер. с англ. - СПб.: БХВ-Петербург, 2001. - 928 с.

2. Шлее М. Qt. Профессиональное программирование на С++. - СПб: БХВ-Петербург, 2005. - 544 с.: ил.

3. Роберт Дж. Оберг. Технология COM+. Основы и программирование: Пер. с англ.-- М.: «Вильямс», 2000. -- С. 480.

4. Деннинг А. ActiveX для профессионалов: Пер. с англ. -- СПб.: Питер, 1998. -- 624 с.

Размещено на Allbest.ru


Подобные документы

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.