В предыдущих двух главах говорилось о том, что технологии OLE и ActiveX основаны на модели компонентных объектов — СОМ. Как вы помните, СОМ определяет механизмы предоставления объектом своих свойств и методов, а также принципы межзадачного взаимодействия объектов и контейнеров. В этой главе вы познакомитесь с библиотекой активных шаблонов — ATL (ActiveTemplateLibrary), с помощью которой можно легко создавать СОМ-объекты, элементы управления ActiveXи многое другое. ATLтакже содержит встроенные средства поддержки большинства базовых интерфейсов СОМ.
Мы создадим простое ATL-приложение, в котором будут совмещены возможности сгенерированного шаблонного проекта Polygonи элемента управления ActiveX, разработанного нами в предыдущей главе. Затем мы встроим полученный СОМ-объект в HTML-документ, который можно просматривать с помощью броузера InternetExplorer.
Создание ATL-проекта Polygon
ATL-проекты создаются с помощью мастера ATLCOMAppWizard. Делается это следующим образом.
1. В окне компилятора VisualC++ в меню Fileвыберите команду Newи в открывшемся диалоговом окне перейдите на вкладку Projects.
2. Выберите элемент ATLCOMAppWizard.
3. В качестве имени проекта введите Polygon(рис. 23.1).
После щелчка на кнопке ОК откроется окно мастера ATLCOMAppWizard(рис. 23.2).
Рис. 23.1. Выбор типа проекта
Рис. 23.2. Окно мастера ATL-проекта
В группе опций ServerType установите переключатель DynamicLinkLibrary (DLL) и щелкните на кнопке Finish. Откроется окно NewProjectInformation с итоговой информацией о создаваемом ATL-проекте (рис. 23.3).
Щелкните на кнопке ОК, чтобы запустить процесс генерирования кода программы.
Пока что мастер создал лишь оболочку проекта, в которую необходимо добавить один или несколько элементов управления. Это можно сделать с помощью мастера ATL-объектов, который вызывается по команде NewATLObject... из меню Insert(рис. 23.4).
Рис. 23.4. Мастер ATL Object Wizard позволяет добавлять в ATL-проект
различные элементы управления
В окне мастера в списке Category выберите элемент
Controls, затем в списке Objects— элемент FullControl и
щелкните на кнопке Next. В открывшемся диалоговом окне вам представится возможность
задать различные параметры конфигурации создаваемого элемента управления.
Сначала на вкладке Names в поле ShortName введите имя объекта — Polyctl. Все
остальные поля будут автоматически инициализированы самим мастером (рис. 23.5).
Рис. 23.5. В окне свойств можно установить характеристики элеменета управления
Теперь перейдите на вкладку Attributes и установите опции Support ISupportErrorInfo и Support Connection Points (рис. 23.6).
Далее активизируйте вкладку StockProperties и выберите свойство FillColor, которое будет поддерживаться элементом управления (рис. 23.7).
Щелкните на кнопке ОК, после чего мастер добавит в проект код элемента управления.
Процесс завершен, и теперь в меню Build можно выбрать команду Build или RebuildAll для компиляции проекта. По окончании компиляции задайте в меню Tools команду ActiveXControlTestContainer, чтобы протестировать созданный элемент управления.
Рис. 23.7. На вкладке Stock Properties выбираются базовые свойства,
подддерживаемые элементом управления
В окне контейнера в меню Edit выберите команду InsertNewControl, в открывшемся диалоговом окне InsertControl найдите класс PolyCtl, после чего нажмите кнопку ОК.
Этот элемент управления не будет выполнять никаких функций до тех пор, пока мы не свяжем с ним различные свойства и события.
Далее необходимо внести некоторые изменения в сгенерированный мастером ATLCOMAppWizard шаблон проекта Polygon.
Добавление свойства
Свойства элемента управления реализуются посредством интерфейса iPolyCtl.
Чтобы добавить новое свойство, в окне компилятора VisualC++ перейдите на вкладку
ClassView, выберите интерфейс IPolyCtl и щелкните правой кнопкой мыши,
после чего в открывшемся контекстном меню выберите команду AddProperty....
На экране появится диалоговое окно AddPropertytoInterface(рис.
23.9).
Рис. 23.9. В окне Add to Property to Interface можно добавить к
элементу управления новое свойство
Из списка PropertyType выберите тип данных short, затем в поле PropertyName введите имя свойства Sides и щелкните на кнопке ОК. Компилятор MIDL(программа, которая создает файлы с расширением IDL) сгенерирует методы get_Sides()и put_sides(),управляющие получением и установкой значения данного свойства. Прототипы этих функций добавляются в файл POLYCTL.H, а их базовые реализации — в файл POLYCTL.CPP. Мы к ним еще вернемся.
Для нашего проекта также необходим интерфейс точек подключения (connectionpoints), формирующий канал передачи сообщений между элементом управления и его контейнером. СОМ-объект может иметь несколько точек подключения и, кроме того, должен реализовывать интерфейс контейнера точек подключения — iConnectionPointContainer.
Прежде всего нам нужно добавить к интерфейсу диспетчеризации событий _IPolyCtlEventsдва метода — clickin() и ClickOut(), которые сигнализируют о том, что щелчок мышью выполнен соответственно внутри и вне многоугольника, рисуемого в элементе управления. Перейдите на вкладку ClassView, щелкните правой кнопкой мыши на элементе _IPolyCtlEventsи выберите из контекстного меню команду AddMethod. В открывшемся диалоговом окне AddMethodtoInterface в списке ReturnType укажите тип возвращаемого значения void, в поле MethodName введите имя метода Clickin, а в поле Parameters задайте описание входных параметров х и у, как показано на рис. 23.10. Повторите эту процедуру для метода ClickOut.
Строки с описанием данных методов будут добавлены в файл POLYGON. IDL— библиотеку типов элемента управления. Прежде чем переходить к следующему шагу, скомпилируйте библиотеку типов, щелкнув на имени указанного файла на вкладке FileView и выбрав в контекстном меню команду CompilePOLYGON.IDL.
Далее на вкладке ClassViewщелкните правой кнопкой мыши на элементе
CPolyCtl и выберите из контекстного меню команду ImplementConnectionPoint.
В открывшемся одноименном диалоговом окне (рис. 23.11) должна содержаться
единственная вкладка POLYGONLib(это название библиотеки типов элемента
управления). В списке Interfaces перечисляются интерфейсы диспетчеризации,
описанные в данной библиотеке. В нашем случае такой интерфейс один: _lPolyCtlEvents.
В поле Filename указано имя файла (POLYGONCP.H), в который будет помещен
специальный код, управляющий транспортировкой сообщений между элементом управления
и контейнером. Поставьте метку напротив интерфейса_IPolyCtlEventsи нажмите
кнопку ОК
Рис. 23.10. Окно Add Method to Interface
Рис. 23.11. Окно Implement Connection Point
В результате выполненных действий будет создан файл POLYGONCP.H, содержащий реализацию класса CProxy_iPolyCtlEvents, потомка класса iConnectionPointlmpl, и двух его методов, Fire_ClickIn() и Fire_ClickOut(), управляющих вызовом упоминавшихся ранее методов ClickIn() и ClickOut().В файле POLYCTL.H в список предков класса CPolyCtl будет добавлен класс CProxy_iPolyCtlEvents, а в схему СОМ-интерфейсов будет помещена запись
COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
Кроме того, будет обновлена схема точек подключения класса CPolyCtl:
BEGIN_CONNECTION_POINT_MAP(CPolyCtl)
CONNECTION_POINT_ENTRY(IID_IPropertyNotifySink)
CONNECTION_POINT_ENTRY(DIID_I PolyCtlEvents)
END_CONNECTION_POINT_MAP()
Добавление обработчика сообщения
Обработчик сообщения wm_lbuttondown необходим для определения момента, когда
пользователь щелкает левой кнопкой мыши на элементе управления. Перейдите
на вкладку ClassView, щелкните правой кнопкой мыши на элементе CPolyCtl
и выберите из контекстного меню команду AddWindowsMessageHandler. В
открывшемся диалоговом окне в левом списке выберите сообщение wm_lbuttondown,
щелкните на кнопке AddHandler и нажмите кнопку ОК.
В результате в файл POLYCTL.H будет добавлена стандартная реализация метода OnLButtonDown(), а в схеме сообщений класса CPolyCtl появится новая запись:
BEGIN_MSG_MAP(CPolyCtl)
CHAIN_MSG_MAP(CComControl<CPolyCtl>)
DEFAULT_REFLECTION_HANDLER()
MESSAGE_HANDLER(WM_LB0TTONDOWN, OnLButtonDown)
END MSG MAP()
Внесение изменений в файл POLYCTL.H
Следующим шагом будет внесение некоторых изменений в файл POLYCTL.H, текст которого показан ниже. Дополнения и изменения выделены полужирным шрифтом.
// PolyCtl.h: Объявление класса CPolyCtl
#ifndef _POLYCTL_H_
#define _POLYCTL_H_
#include <math.h>
#include "resource.h"
// основные константы
#include <atlctl.h>
#include "PolygonCP.h"
/////////////////////////////////////////
11 CPolyCtl
class ATL_NO_VTABLE CPolyCtl :
public CComObjectRootEx<CComSingleThreadModel>,
public CStockPropImpKCPolyCtl, IPolyCtl, SIID_IPolyCtl, SLIBID_POLYGONLib>,
public CComControl<CPolyCtl>,
public IPersistStreamInitImpl<CPolyCtl>,
public I01eControlImpl<CPolyCtl>,
public I01eObjectImpl<CPolyCtl>,
public I01eInPlaceActiveObjectImpl<CPolyCtl>,
public IViewObjectExImpKCPolyCtl>,
public I01eInPlaceObjectWindowlessImpl<CPolyCtl>,
public ISupportErrorlnfo,
public IConnectionPointContainerImpl<CPolyCtl>,
public IPersistStorageImpl<CPolyCtl>,
public ISpecifyPropertyPagesImpl<CPolyCtl>,
public IQuickActivateImpl<CPolyCtl>,
public IDataObjectImpl<CPolyCtl>,
public IProvideClassInfo2Impl<SCLSID_PolyCtl, SDIID_IPolyCtlEvents,
&LIBID_POLYGONLib>,
public IPropertyNotifySinkCP<CPolyCtl>,
public CComCoClass<CPolyCtl, SCLSID_Po.lyCtl>
public CProxy_IPolyCtlEvents< CPolyCtl > { public:
CPolyCtl ()
{
m_nSides =6;
// по умолчанию строится шестиугольник
m_clrFillColor = RGB(OxFF, OxFF, 0); // желтый цвет заливки
}
DECLARE_REGISTRY_RESOURCEID(IDR_POLYCTL) DECLARE PROTECT FINAL CONSTRUCT))
BEGIN_COM_MAP(CPolyCtl)
COM_INTERFACE_ENTRY(IPolyCtl)
COM_INTERFAOE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IViewObjectEx)
COM_INTERFACE_ENTRY(IViewObject2)
COM_INTERFACE_ENTRY(IViewObject)
COM_INTERFACE_ENTRY(IDlelnPlaceObjectWindowless)
COM_INTERFACE_ENTRY(I01eInPlaceObject)
COM_INTERFACE_ENTRY2(IQleWindow, IQlelnPlaceObjectWindowless)
COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)
COM_INTERFACE_ENTRY(I01eControl)
COM_INTERFACE_ENTRY(IQleObject)
COM_INTERFACE_ENTRY(IPersistStreamlnit)
COM_INTERFACE_ENTRY2(IPersist, IPersistStreamlnit)
COM_INTERFACE_ENTRY(ISupportErroriInfo)
COM_INTERFACE_ENTRY(IConnectionPointContainer)
COM_INTERFACE_ENTRY(ISpecifyPropertyPages)
COM_INTERFACE_ENTRY(IQuickActivate)
COM_INTERFACE_ENTRY(IPersistStorage)
COM_INTERFACE_ENTRY(IDataObject)
COM_INTERFACE_ENTRY(IProvideClassInfo)
COM_INTERFACE_ENTRY(IProvideClassInfo2)
COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer) ^ END_COM_MAP()
BEGIN_PROP_MAP(CPolyCtl)
PROP_DATA_ENTRY("_cx",m_sizeExtent.ex, VT_UI4) PROP_DATA_ENTRY("_Gy",m_sizeExtent.cy, VT_UI4) PROP_ENTRY("FillColor",DISPID_FILLCOLOR, CLSID_StockColorPage)
END_PROP_MAPt)
BEGIN_CONNECTION_POINT_MAP(CPolyCtl)
CONNECTION_POINT_ENTRY(IID_IPropertyNotifySink) CONNECTION_POINT_ENTRY(DIID_IPolyCtlEvents)
END_CONNECTION_POINT_MAP ()
BEGIN_MSG_MAP(CPolyCtl)
CHAIN_MSG_MAP(CComControl<CPolyCtl>)
DEFAULT_REFLECTION_HANDLER() END_MSG_MAP ()
// ISupportErrorlnfo
STDMETHOD(InterfaceSupportsErrorInfo) (REFIID riid)
{
static const IID* arr[]=
{
&IID_IPolyCtl,
{
for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
{
if (InlineIsEqualGDID(*arr[i], riid))
return S_OK; } return S_FALSE;
}.
// IViewObjectEx
DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATOS_OPAQUE)
// IPolyCtl public:
STDMETHOD(get_Sides)(/*[out,retval]*/ short *pVal);
STDMETHOD(put_Sides) </*[in]*/short newVal);
HRESULT OnDraw(ATL_DRAWINFOS di);
LRESULT OnLButtonDown(UINT uMsg,
WPARAM wParam, LPARAM IParam, BOOLS bHandled)
OLE_COLOR m_clrFillColor;
short m_nSides; POINT m_arrPoint[10];
};
#endif // _ POLYCTL_H_
В конструкторе класса CPolyCtlустанавливается, что по умолчанию число сторон многоугольника, рисуемого в элементе управления, равно шести (минимальное — 3, максимальное — 10), а для заливки используется желтый цвет. Для вычисления координат вершин многоугольника потребуются тригонометрические функции, поэтому в проект включается библиотека МАТН.Н.
Стандартные реализации функций OnDraw( ) и OnLButtonDown( ) были удалены из файла, так как мы значительно расширим их и включим в файл POLYCTL.CPP.
Реализация методов элемента управления
Ниже приведен текст файла POLYCTL.CPP. Все дополнения и изменения выделены полужирным шрифтом.
// PolyCtl.cpp: Реализация класса CPolyCtl
#include "stdafx.h"
#include "Polygon. h"
#include "PolyCtl.h"
#include <time.h>
#include <string.h>
////////////////////////////////
// CPolyCtl
HRESULT CPolyCtl: : OnDraw (ATL_DRAHINFO& di)
{
struct tm *date_time;
time_t timer;
static TEXTMETRIC tin;
RECTS rc = *(RECT*)di.prcBounds; HDC hdc = di.hdcDraw;
COLORREF colFore;
HBRUSH hOldBrush, hBrush;
HPEN hOldPen, hPen;
// Приведение переменной m_clrFillColor
к типу COLORREF
OleTranslateColor(m_clrFillColor, NULL, ScolFore);
// Выбор пера и кисти для рисования
окружности
hPen - (HPEN)GetStockObject(BLACK_PEN);
hOldPen = (HPEN)SelectObject (hdc, hPen);
hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);
hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);
const double pi = 3.14159265358979; POINT ptCenter;
double dblRadiusx = (rc.right - rc.left)
/ 2;
double dblRadiusy = (rc.bottom - rc.top) / 2;
double dblAngle = 3 * pi / 2;
double dblDiff = 2 * pi / m_nSides;
ptCenter.x = (rc.left + rc.right) / 2;
ptCenter.у = (rc.top + rc.bottom) / 2;
// Вычисление координат вершин
for (int i = 0; i < m_nSides; i++) {
m arrPoint[i].x = (long) \
(dblRadiusx*cos(dblAngle)+ptCenter.x+0.5);
m_arrPoint[i].y = (long) \
(dblRadiusy*sin (dblAngle) -1-ptCenter. y+0.5) ;
dblAngle += dblDiff; } Ellipse(hdc, rc.left, rc.top, rc.right, rc.bottom);
// Создание и выбор кисти для заливки
многоугольника
hBrush = CreateSolidBrush(colFore);
SelectObject(hdc, hBrush);
Polygon(hdc, Sm_arrPoint[0], m_nSides);
// Вывод даты и времени
time(Stimer);
date_time = localtime(<<timer);
const char* strtime;
strtime = asctime(date_time);
SetBkMode(hdc, TRANSPARENT);
SetTextAlign(hdc, TA_CENTER | TA_TOP); ExtTextOut(hdc, (rc.left + rc.right)/2,
(rc.top + rc.bottom - tan.tmHeight)/2,
ETO_CLIPPED, Src, strtime, strlen (strtime) -1,NULL);
// Восстановление старых пера и кисти
SelectObject(hdc, hOldPen) ;
SelectObject(hdc, hOldBrush) ;
DeleteOb ject (hBrush) ;
return S_OK;
LRESULt CPolyCtl: : OnLButtonDown (UINT uMsg, WPJUWM wParam,
LPARAM 1 Par am, BOOLS bHandled)
{
HRGNhRgn;
WORDxPos= LOWORD(lParam) ; // положение указателя по горизонтали
WORDyPos= HIWORD(lParam) ; // положение указателя по вертикали
// Создание многоугольника по списку координат вершин
hRgn = CreatePolygonRgn(sm_arrPoint[0] , m_nSides, WINDING);
// Если точка щелчка попадает внутрь многоугольника,
// то генерируется событие Clickln,
// в противном случае - событие ClickOut
if (PtInRegion(hRgn, xPos, yPos) )
Fire_ClickIn (xPos , yPos) ; else
Fire_ClickOut (xPos , yPos) ;
// Освобождение дескриптора
DeleteOb ject (hRgn) ;
return 0 ;
}
STDMETHODIMP CPolyCtl::get_Sides(short *pVal) (
*pVal = m_nSides;
return S_OK; }
STDMETHODIMP CPolyCtl::put_Sides(short newVal)
{
if (newVal > 2 ££ newVal < 11) {
m_nSides = newVal;
FiifeViewChangeO ;
return S_OK; ) else
return Error(_T("Must have between 3 and 10 sides"));
}
Отображаемые дата и время будут обновляться каждый раз после выполнения щелчка на элементе управления. Метод put_Sides() изменен таким образом, чтобы вызывать функцию FireViewChange(), которая, в свою очередь, вызывает функцию invalidateRect(), обозначающую область перерисовки элемента управления как недействительную. Если этого не сделать, изображение элемента управления не будет обновляться после щелчка на нем мышью.
Добавление страницы свойств
С помощью того же мастера ATL-объектов можно добавить в элемент управления
страницу свойств. Для этого выберите в меню Insert командуNew ATL Object...
(рис. 23.13).
Рис. 23.13. С помощью мастера ATL Object Wizard можно добавить в проект
страницу свойств
Выделите категорию Controls, в ней — элемент PropertyPageи щелкните на кнопке Next. В следующем окне мастера можно установить параметры, определяющие работу страницы свойств. На вкладке Namesв поле ShortNameвведите имя объекта — PolyProp. Все остальные поля будут заполнены мастером автоматически (рис. 23.14).
Рис. 23.14. Задание параметров создаваемой страницы свойств
Теперь перейдите на вкладку Strings и заполните
поля Title(текст ярлычка вкладки) и DocString(строка описания),
а поле Helpfile (ассоциированный файл справки) очистите (рис. 23.15).
Рис. 23.15. На вкладке Strings следует заполнить поля Title и Doc String
После щелчка на кнопке ОК будут созданы новые файлы POLYPROP.H, POLYPROP.CPPи POLYPROP.RGS. Далее необходимо изменить внешний вид страницы свойств. Откройте с помощью вкладки ResourceViewдиалоговое окно с идентификатором lDD_PObYPROp, поменяйте существующую надпись на Sides: и добавьте текстовое поле с идентификатором IDC_SIDEs(рис. 23.16).
Рис. 23.16. Изменение внешнего вида страницы свойств
Теперь нужно добавить обработчик, управляющий изменением
значения поля idc_sides. Для этого выполните щелчок правой кнопкой мыши на
поле и выберите в контекстном меню команду Events. В появившемся окне выберите
в списке Classorobjecttohandle элемент IDC_SIDBS, а затем в списке NewWindowsMessages/Events—
сообщение EN_CHANGE. Щелкните на кнопке AddHandler, после чего в открывшемся
окне AddMemberFunctionбудет предложено имя обработчика (рис. 23.17).
Рис. 23.17. Добавление обработчика сообщений
Примите предлагаемое имя OnChangeSides и закройте оба окна. В результате в файл POLYPROP.H будет добавлена стандартная реализация данного обработчика, а в схеме сообщений класса CPolyProp появится новая запись:
BEGIN_MSG_MAP(CPolyProp)
CHAIN_MSG_MAP(IPropertyPageImpKCPolyProp>)
COMMAND_HANDLER(IDC_SIDES, EN_CHANGE, OnChangeSides)
END_MSG_MAP ()
Следующим шагом будет внесение изменений в файл POLYPROP.H:
// PolyProp.h: Объявление класса CPolyProp
#ifndef _POLYPROP_H_
#define _POLYPROP_H_
#include "resource.h"
// основные константы
#include "Polygon.h"
EXTERN_C const CLSID CLSID_PolyProp;
///////////////////////////////////////////////
II CPolyProp
class ATL_NO_VTABLE CPolyProp :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CPolyProp, &CLSID_PolyProp>,
public IPropertyPageImpl<CPolyProp>,
public CDialogImpl<CPolyProp> { public:
CPolyProp ( ) {
m_dwTitleID = IDSJTITLEPolyProp; m_dwHelpFileID - IDS_HELPFILEPolyProp; m_dwDocStringID = IDS_DOCSTRINGPolyProp;
}
enura (IDD = IDD_POLYPROP};
DECLARE_REGISTRY_RESOURCEID ( IDR_POLYPROP) DECLARE_PROTECT_FINAL_CONSTRUCT ( )
BEGIN_COM_MAP (CPolyProp) -
COM_INTERFACE_ENTRY ( I Proper tyPage ) END_COM_MAP ( )
BEGIN_MSG_MAP (CPolyProp)
CHAIN_MSG_MAP ( IPropertyPageImpKCPolyProp>) COMMAND_HANDLER(IDC_SIDES, EN_CHANGE, OnChangeSides)
END_MSG_MAP ( )
STDMETHOD (Apply) (void) 1
OSES_CONVERSION ;
ATLTRACE (_T ( "CPolyProp: :Apply\n") ) ;
for (UINT i = 0; i < m_nObjects; i++)
{
CComQIPtr<IPolyCtl , SIID_IPolyCtl>
pPoly (m_ppOnk[i]) ;
short nSides = ( short) GetDlgl temlnt (IDC_SIDES) ;
if FAILED (pPoly->put_Sides (nSides) ) {
CComPtr<IErrorInf o> pError
; CComBSTR strError;
GetErrorInfo(0, SpError) ;
pError->GetDescription (fistrError) ;
MessageBox(OLE2T(strError) , _T ("Error"),
MB_ICONEXCLAMATION) ;
return E_FAIL; } } m_bDirty = FALSE;
return S_OK; }
LRESULT OnChangeSides(WORD wNotifyCode, WORD wID,
HWND hWndCtl, BOOL& bHandled) {
SetDirty(TRCE);
return 0;
}
};
#endif //_POLYPROP_H_
Страница свойств может быть вызвана сразу несколькими клиентами. Для обслуживания всех клиентов в функции Apply() запускается цикл и в нем вызывается метод put_Sides() для каждого клиента, данные которого были введены в текстовое поле.
Страница свойств добавляется в проект с помощью единственной строки в файле POLYCTL.H:
BEGIN_PROP_MAP(CPolyCtl)
PROP_DATA_ENTRY("_c.x", m_sizeExtent.ex, VT_UI4)
PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
PROPJ3NTRY("FillColor", DISPID_FILLCOLOR, CLSID_StockColorPage)
PRQP_ENTRY("Sides", 1, CLSID_PolyProp) END_PROP_MAP 0
Теперь можно приступать к тестированию элемента управления на Web-странице.
Тестирование элемента управления ATLна Web-странице
Мастер ATL-объектов создает исходный элемент управления вместе с тестовым HTML-файлом, который находится в папке проекта. Он называется POLYCTL.HTM и может быть открыт в броузере Microsoft Internet Explorer. С помощью данного файла можно протестировать созданный нами элемент управления. Но прежде в этот файл следует внести изменения, выделенные ниже полужирным шрифтом:
<HTML>
<HEAD>
<TITLE>ATL 3.0 test page for object PolyCtl</TITLE>
</HEAD>
<BODY>
<OBJECT ID="PolyCtl"
CLASSID="CLSID:4CBBC676-507F-11DO-B98B-000000000000"> </OBJECT>
<SCRIPT LM>>GOAGE="VBScript"> <! —
Sub PolyCtl_ClickIn(x, y)
PolyCtl.Sides = PolyCtl.Sides + 1
End Sub
Sub PolyCtl_ClickOut(x, у)
PolyCtl.Sides = PolyCtl.Sides - 1
End Sub —>
</SCRIPT>
</BODY>
</HTML>
Теперь запустите Internet Explorer и откройте в нем файл POLYCTL.HTM. Начальное содержимое Web-страницы показано на рис. 23.18.
Выполните несколько щелчков мышью внутри и вне многоугольника. Как вы убедитесь,
число вершин станет автоматически увеличиваться >> уменьшаться, если
только не будут достигнуты граничные значения 2 и 11 — в этом случае выдается
сообщение об ошибке Must have between 3 and 10 sides. На
рис. 23.19 показано, как изменится внешний вид элемента управления после двух
щелчков внутри многоугольника.
Рис. 23.18. Исходный вид созданного вами элемента управления ATL
Примечание
Убедитесь, что в свойствах Internet Explorer установлен низкий уровень безопасности.
По умолчанию задается средний уровень, но в этом случае выполнение сценариев
неподписанных элементов управления ActiveX запрещено.
Рис. 23.19. Вид элемента управления после двух последовательных щелчков
на нем