Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Паппас К., Мюррей У. - Visual C++ 6. Руководство разработчика - 2000

.pdf
Скачиваний:
288
Добавлен:
13.08.2013
Размер:
4.96 Mб
Скачать

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

Критерии разработки элементов управления

Чтобы создаваемый элемент управления ActiveXполучился как можно более привлекательным

ифункциональным, необходимо определиться по ряду моментов.

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

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

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

Класс COleControl

Элементы управления ActiveX порождаются от MFC -класса COleControl. В приведенном ниже листинге содержится часть файла AFXCTL.H с сокращенным описанием данного класса. Мы не станем подробно объяснять назначение каждой части файла, а лишь наглядно проиллюстрируем наиболее важные моменты.

//Это класс библиотеки MFC .

//Copyright (С)1992-1998Microsoft Corporation

//All rights reserved.

//Данный исходный код служит дополнением к справочному

//руководству и сопутствующей электронной документации по MFC .

//Обращайтесь к ним для получения более полной информации.

///////////////////////////////////

//AFXCTL.H поддержка элементов управления OLE

///////////////////////////////////

//Базовые события

#define EVENT_STOCK_CLICK() \

{afxEventStock, DISPID_CLICK, _T("Click"),VTS_NONE }, #define EVENT_STOCK_DBLCLICK() \

{afxEventStock, DISPID_DBLCLICK, _T("DblClick"), VTS_NONE }, #define EVENT_STOCK_KEYDOWN() \

{afxEventStock, DISPID_KEYDOWN, _T("KeyDown"), VTS_PI2 VTS_I2 }, #define EVENT_STOCK_KEYPRESS() \

{afxEventStock, DISPID_KEYPRESS, _T("KeyPress"), VTS_PI2 }, #define EVENT_STOCK_KEYUP() \

{afxEventStock, DISPID_KEYUP, JTC'KeyUp") , VTS_PI2 VTS_I2 }, #define EVENT_STOCK_MOUSEDOWN() \

( afxEventStock, DISPID_MOUSEDOWN, _T("MouseDown"), \ VTS_I2 VTS_I2 VTS_XPOS_PIXELS VTS_YPOS_PIXELS },

#define EVENT_STOCK_MOUSEMOVE() \

{ afxEventStock, DISPID_MOUSEMOVE, _T("MouseMove"), \ VTS_i2 VTS_i2 vts_xpos_pixels vts_ypos_pixels },

411

#define EVENT_STOCK_MOOSEUP() \

{ afxEventStock, DISPID_MOUSEUP, _T("MouseUp"), \ VTS_I2 VTS_I2 VTS_XPOS_PIXELS VTS_YPOS_PIXELS },

#define EVENT STOCK ERROREVENTO \{ afxEventStock, DISPID_ERROREVENT, _T("Error"),\

VTS_I2 VTS_PBSTR VTS_SCODE VTS_BSTR VTS_BSTR VTS_I4 VTS_PBOOL },

#define EVENT_STOCK_READYSTATECHANGE () \

{ afxEvtentStock, DISPID_READYSTATECHANGE, _T("ReadyStateChange"), \ VTS 14 },

///////////////////////////////////

// Базовые свойства

#define DISP_PROPERTY_STOCK(theClass, szExternalName, dispid, pfnGet, pfnSet, vtPropType) \

{ _T(szExternalName), dispid, NULL, vtPropType, \ (AFX_PMSG)(void (theClass::*)(void)JSpfnGet, \ (AFX_PMSG)(void (theClass::*)(void))SpfnSet, 0, afxDispStock ), \

#define D1SP_STOCKPROP_APPEARANCE() \

DISP_PROPERTY_STOCK(C01eControl, "Appearance", DISPID_APPEARANCE, \ COleControl::GetAppearance, COleControl::SetAppearance, VT_I2)

#define DISP_STOCKPROP_BACKCOLOR() \

DISP_PROPERTY_STOCK(COleControl, "BackColor", DISPID_BACKCOLOR, \ COleControl::GetBackColor, COleControl::SetBackColor, VT_COLOR)

#define DISP_STOCKPROP_BORDERSTYLE() \

DISP_PROPERTY_STOCK(COleControl, "BorderStyle", DISPID_BORDERSTYLE, \ COleControl::GetBorderStyle, COleControl::SetBorderStyle, VT_I2)

#define DISP_STOCKPROP_CAPTION() \

DISP_PROPERTY_STOCK(COleControl, "Caption", DISPID_CAPTION, \ COleControl::GetText, COleControl::SetText, VT_BSTR)

#define DISP_STOCKPROP_ENABLED() \

DISP_PROPERTY_STOCK(COleControl, "Enabled", DISPID_ENABLED, \ COleControl::GetEnabled, COleControl::SetEnabled, VT_BOOL)

#define DISP_STOCKPROP_FONT() \

DISP_PROPERTY_STOCK (COleControl, "Font",' DISPID FONT, \ COleControl::GetFont, COleControl::SetFont, VT_FONT) Idefine DISP_STOCKPROP_FORECOLOR() \

DISP_PROPERTY_STOCK(COleControl, "ForeColor", DISPID_FORECOLOR, \ COleControl::GetForeColor, COleControl::SetForeColor, VT_COLOR)

Idefine DISP_STOCKPROP_HWND() \

DISP_PROPERTY_STOCK(COleControl, "hWnd", DISPID_HWND, \ COleControl::GetHwnd, SetNotSupported, VT_HANDLE)

Idefine DISP_STOCKPROP_TEXT() \

DISP_PROPERTY_STOCK(COleControl, "Text", DISPID_TEXT, \ COleControl::GetText, COleControl::SetText, VT_BSTR)

Idefine DISP_STOCKPROP_READYSTATE() Л

DISP_PROPERTY_STOCK(COleControl, "ReadyState", DISPID_READYSTATE, \ COleControl::GetReadyState, SetNotSupported, VT_I4)

///////////////////////////////////

// Базовые методы

Idefine DISP_FUNCT1ON_STOCK(theClass, szExternalName, dispid, pfnMember, vtRetVal, vtsParams) \

( _T(szExternalName), dispid, vtsParams, vtRetVal, \ (AFX_PMSG)(void (theClass::*)(void))SpfnMember, (AFX_PMSG)0, 0, \ afxDispStock }, \

#define DISP_STOCKFDNC_REFRESH() \

DISP_FUNCTION_STOCK(COleControl, "Refresh", DISPID_REFRESH, \ COleControl::Refresh, VT_EMPTY, VTS_NONE)

#define DISP_STOCKFUNC_DOCLICK() \

412

DISP_FUNCTION_STOCK(COleControl, "DoClick", DISPID_DOCLICK, \ COleControl::DoClick, VT.EMPTY, VTS_NONE)

///////////////////////////////////

//COleControl — базовыйклассэлементауправления.

//реализованного на C++ с использованием MFC classCOleControl: publicCWnd

//Базовые методы

void Refresh () ; void DoClick () ;

//Базовые свойства short GetAppearance();

void SetAppearance(short); OLE_COLOR GetBackColorO ; void SetBackColor(OLE_COLOR); short GetBorderStyle();

void SetBorderStyle(short); BOOL GetEnabledO ;

void SetEnabled(BOOL); CFontHolderS InternalGetFont(); LPFONTDISP GetFontO;

void SetFont(LPFONTDISP); OLE_COLOR GetForeColor(); void SetForeColor(OLE_COLOR); OLE_HANDLE GetHwnd();

const CStringS InternalGetText () ; BSTR GetText () ;

void SetText(LPCTSTR); long GetReadyState();

void InternalSetReadyState(long INewReadyState) ,

//Внешние свойства

short AmbientAppearance(); OLE_COLOR AmbientBackColor(); CString AmbientDisplayNarae(); LPFONTDISP AmbientFont(); OLE_COLOR AmbientForeColor(); LCID AmbientLocalelDO;

CString AmbientScaleUnits(>; short AmbientTextAlign(); BOOL AmbientUserModeO;

BOOL AmbientUIDeadO;

BOOL AmbientshowGrabHandles(); BOOL AmbientShowHatching(); // Генерация событий

void AFX_CDECL FireEvent(DISPID dispid, BYTE* pbParams,

// Функции генерации базовых событий

void FireKeyDown(USHORT* pnChar, short nShiftState); void FireKeyUp(USHORT* pnChar, short nShiftState);

void FireKeyPress(USHORT* pnChar); void FireMouseDown(short nButton, short nShiftState,

OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y) ;

void FireMouseDp(short nButton, short nShiftState, OLE_XPOS_PIXELS X, OLE_YPOS_PIXELS y);

void FireMouseMove(short nButton, short nShiftState, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);

void FireClickO; void FireDblClickO ;

void FireError(SCODE scode, LPCTSTR IpszDescription,

413

UINT nHelpID. = 0) ;

void FireReadyStateChange();

// Базовые события

void KeyDown(USHORT* pnChar); void KeyUp(USHORT* pnChar);

void ButtonDown(USHORT iButton, UINT nFlags, CPoint point); void ButtonUp(USHORT iButton, UINT nFlags, CPoint point); void ButtonDblClk(USHORT iButton, UINT nFlags, CPoint point);

// Базовые свойства

OLE_COLOR m_clrBackColor;

//

Цвет фона

OLE_COLOR m_clrForeColor;

//

Цвет переднего плана

CString m_strText;// Текст/Надпись

CFontHolder m_font;

// Шрифт

 

HFONT m_hFontPrev;// Предыдущий

шрифт

short m_sAppearance; .

// Внешний вид

short m_sBorderStyle;

// Стиль рамки

BOOLm_bEnabled; // Доступность

 

longm_lReadyState;

// Состояние готовности

// Схема сообщений

 

 

 

protected: //{{AFX_MSG(COleControl)

afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags), afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg void OnMouseMove(UINT nFlags, CPoint point);

afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); afx_msg void OnMButtonDown(UINT nFlags, CPoint point); afx_msg void OnMButtonUp(UINT nFlags, CPoint point); afx_msg void OnMButtonDblClkfUINT nFlags, CPoint point); afx_msg void OnRButtonDown(UINT nFlags, CPoint point); afx_msg void OnRButtonUp(UINT nFlags, CPoint point); afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point); afx_msg void OnlnitMenuPopup(CMenu*, UINT, BOOL);

afx_msg void OnMenuSelect(UINT nltemlD, UINT nFlags, HMENU hSysMenu), afx_msg LRESULT OnSetMessageString(WPARAM wParam, LPARAM IParam); afx_msg void OnEnterldle(UINT nWhy, CWnd* pWho);

afx_msg void OnCancelMode(); afx_msg void OnPaint(CDC* pDC);

afx_msg BOOL OnEraseBkgnd(CDC* pDC) ;

afx_msg void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg void OnSysKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg int OnMouseActivate(CWnd *pDesktopWnd, UINT nHitTest, UINT message);

afx_msg LRESULT OnSetText(WPARAM wParam, LPARAM IParam); afx_msg BOOL OnNcCreate(LPCREATESTRUCT IpCreateStruct);

afx_msg void OnDestroyO; afx_msg void OnKillFocus(CWnd* pNewWnd); afx_msg void OnSetFocus(CWnd* pOldWnd) ;

afx_msg void OnNcPaintO;

afx_msg void OnNcCalcSize(BOOL bCalcValidRects,

NCCALCSIZE_PARAMS* Ipncsp); afx_msg UINT OnNcHitTest(CPoint point);

414

afx_msg void OnNcLButtonDown(UINT nHitTest, CPoint point); afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); afx_msg UINT OnGetDlgCode();

afx_msg int OnCreate(LPCREATESTRUCT IpCreateStruct); afx_msg void OnSize(UINT nType, int ex, int cy) ; afx_msg void OnMovelint x, int y);

afxjmsg void OnShowWindow(BOOL bShow, UINT nStatus); //))AFX_MSG afx_msg LRESULT OnOcraCtlColorBtn(WPARAM wParam, LPARAM IParam); afx_msg LRESULT OnOcmCtlColorDlg(WPARAM wParam, LPARAM IParam); afx_msg LRESULT OnOcmCtlColorEdit(WPARAM wParam, LPARAM IParam); afx_msg LRESULT OnOcmCtlColorListBox(WPARAM wParam, LPARAM IParam); afx_msg LRESULT OnOcmCtlColorMsgBox(WPARAM wParam, LPARAM IParam); afx_msg LRESULT OnOcmCtlColorScrollBar(WPARAM wParam, LPARAM IParam) , afx_msg LRESULT OnOcmCtlColorStatic(WPARAM wParam, LEARAM IParam); DECLARE_MESSAGE_MAP()

// вспомогательные обработчики

void OnButtonUp(USHORT nButton, UINT nFlags, CPoint point); void OnButtonDown(USHORT nButton, UINT nFlags, CPoint point); void OnButtonDblClk(USHORT nButton, UINT nFlags, CPoint point);

//Схемы интерфейсов public:

//IPersistStorage

BEGIN_INTERFACE_PART(Persiststorage, IPersistStorage) INIT_INTERFACE_PART(COleControl, PersistStorage) STDMETHOD(GetClassID)(LPCLSID);

STDMETHOD (IsDirty) (); STDMETHOD(InitNew)(LPSTORAGE); STDMETHOD(Load)(LPSTORAGE); STDMETHOD(Save)(LPSTORAGE, BOOL); STDMETHOD(SaveCompleted)(LPSTORAGE); STDMETHOD(HandsOffStorage)(); END_INTERFACE_PART_STATIC(PersistStorage) // IOlelnPlaceObject

BEGIN_INTERFACE_PART(OlelnPlaceObject, IQlelnPlaceObjectWindowless) INIT_INTERFACE_PART(COleGontrol, OlelnPlaceObject) STDMETHOD(GetWindow)(HWND*); STDMETHOD(ContextSensitiveHelp)(BOOL); STDMETHOD(InPlaceDeactivate)();

STDMETHOD(OIDeactivate)(); STDMETHOD(SetObjectRects)(LPCRECT, LPCRECT); STDMETHOD(ReactivateAndUndo)();

STDMETHOD(OnWindowMessage)(UINT msg, WPARAM wParam, LPARAM Iparam, LRESULT* plResult);

STDMETHOD(GetDropTarget)(IDropTarget **ppDropTarget); END_INTERFACE_PART(OlelnPlaceObject)

// IQlelnPlaceActiveObject BEGIN_INTERFACE_PART(OleInPlaceActiveObject, IQlelnPlaceActiveObject) INIT_INTERFACE_PART(COleControl, OlelnPlaceActiveObject) STDMETHOD(GetWindow)(HWND*);

STDMETHOD(ContextSensitiveHelp)(BOOL);

STDMETHOD(TranslateAccelerator)(LPMSG);

STDMETHOD(OnFrameWindowActivate)(BOOL);

STDMETHOD(OnDocWindowActivate)(BOOL); STDMETHOD(ResizeBorder)(LPCRECT, LPOLEINPLACEOIWINDOW, BOOL);

STDMETHOD(EnableModeless)(BOOL); END_INTERFACE_PART(OlelnPlaceActiveObject)

415

}

События

События генерируются элементом управления в ответ на выполняемые над ним действия, такие как нажатие определенной комбинации клавиш или щелчок мышью. Примерами событий могут служить KeyUp и KeyDown.

Класс элемента управления ActiveX, порождаемый от класса GOleControl, может иметь собственную специальную схему сообщений, посредством которой события посылаются приложению, содержащему элемент управления. Такое приложение называется контейнером. Дополнительную информацию о событии можно передать с помощью аргументов.

Именно путем передачи событий организуется взаимодействие между элементом управления ActiveXи контейнером. Различаются базовые и пользовательские события. События первого типа могут генерироваться любым элементом управления и по умолчанию обрабатываются классом CQleControl. События второго типа посылаются контейнеру при выполнении над элементом управления действий, указанных разработчиком элемента.

Методы и свойства

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

Доступ к методам и свойствам элемента управления возможен на этапе раннего связывания. При этом методы рассматриваются как обычные функции-члены класса, а свойства представляются парами функций getxxx и setxxx. Доступ к элементу управления на этапе позднего связывания регулируется интерфейсом IDispatch. Контейнер автоматически определяет тип связывания, установленный пользователем. Интерфейс IProvideClassInfo содержит функцию GetClassInfo(), которая возвращает объект ITypelnfо с информацией об элементе управления, взятой из его библиотеки типов.

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

Постоянство

Элементы управления позволяют сохранять свои данные в потоках с помощью интерфейса iPersiststream, а в хранилищах — с помощью интерфейса iPersiststorage. Первый необходим для записи данных в простой последовательный поток, а второй реализует концепцию структурированного хранения составных документов, когда каждый внедренный или связанный объект имеет собственную область хранения в общем хранилище данных документа.

Благодаря механизму постоянства элемент управления ActiveXпри необходимости может записывать значения своих свойств в файл или поток, а затем считывать их. Значения свойств элемента управления могут сохраняться самим контейнером и считываться, скажем, при создании нового экземпляра элемента управления.

Контейнеры

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

Элемент управления ActiveXвыступает в роли переводчика сообщений. Он должен уметь преобразовывать сообщения, получаемые от пользователя, в события, понятные контейнеру. Для каждого события должна быть определена точка входа в контейнере, связанная с обслуживающей процедурой.

416

Свойства контейнера, применимые ко всем внедренным элементам управления, называются внешними (ambient). К таковым, в частности, относятся заданные по умолчанию цвета и шрифты.

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

В данном параграфе мы шаг за шагом пройдем процесс создания шаблона элемента управления ActiveX с помощью мастера MFC ActiveXControlWizard. Затем мы изменим шаблон таким образом, чтобы получить элемент управления, отвечающий нашим требованиям.

Создание ActiveX-шаблона

В окне компилятора MicrosoftVisualC++ выберите в меню File команду New и в открывшемся диалоговом окне установите опцию MFC ActiveX ControlWizard (рис. 22.1). Назовем наш проект

TDCtrl.

Рис. 22.1. Выбор типа проекта

Мастер создает элемент управления в два этапа. Сначала задаются установки всего проекта, такие как число элементов управления, наличие лицензии на выполнение, добавление комментариев в программный код и создание файлов справки (рис. 22.2). Не меняйте опции, заданные по умолчанию.

417

Рис. 22.2. Шаг 1: принимаем опции, заданные по умолчанию

На втором этапе задаются параметры каждого элемента управления, включаемого в проект. Установите в этом окне опцию Available in "InsertObjects" dialog, чтобы название элемента управления появлялось в окне вставки объектов (рис. 22.3.)

418

Рис. 22.3. Шаг 2: параметры элемента управления TDCtrl

Далее на экране появится отчет с перечнем установок проекта (рис 22.4)

Рис. 22.4. Отчет о параметрах создаваемого элемента управления

После щелчка на кнопке ОК мастер автоматически сгенерирует код шаблона элемента управления. Список его классов и глобальных атрибутов представлен на вкладке

ClassView(рис 22.5)

419

Рис. 22.5. Список классов и глобальных атрибутов элемента управления TDCtrl

Для того чтобы скомпилировать проект, выберите в меню Build команду Build илиRebuild All. После завершения этого процесса в папке DEBUG появится файл TDCTRL.OCX.

Элементы управления ActiveX представляют собой небольшие библиотеки динамической компоновки, которые можно тестировать в соответствующих контейнерах. Компания Microsoft предоставляет для этих целей специальную утилиту ActiveXControlTestContainer; запускаемую из меню Tools(рис. 22.6).

420

Соседние файлы в предмете Программирование на C++