Обычно при создании приложения-контейнера для
элемента ActiveX придерживаются следующей
стратегии:
-
Вставляют уже зарегистрированный элемент
ActiveX в форму приложения контейнера,
используя так называемую галерею объектов (Gallery).
-
В одном из классов контейнера определяют
переменную того же типа, что и
класс-оболочка для внедренного элемента.
-
Программируют поведение элемента, управляя
им с помощью этой переменной.
Первый шаг этого алгоритма вы уже выполнили,
теперь введите в состав проекта два новых файла
OpenGLh и OpenGLcpp, которые будут содержать
коды класса-оболочки copenGL. Вот содержимое
файла заголовков (OpenGLh):
#pragma once
//=========== COpenGL wrapper class
class
COpenGL : public CWnd
{
protected:
DECLARE_DYNCREATE(COpenGL)
public:
//==== Метод для добывания CLSID нашего элемента
CLSID const& GetClsidO
{
static
CLSID const clsid =
{
0x519d9ed8, Oxbc4'6, 0x4367,
{ Ox9c, OxcO, 0x49, 0x81, 0x40, Oxf3, 0x94, 0x16
}
};
return
clsid;
}
virtual
BOOL Create(LPCTSTR IpszClassName,
LPCTSTR IpszWindowName, DWORD dwStyle,
const
RECT& rect, CWnd* pParentWnd, UINT nID,
CCreateContext* pContext = NULL)
{
return
CreateControl(GetClsid(), IpszWindowName,
dwStyle, rect, pParentWnd, nID)
}
BOOL Create (LPCTSTR IpszWindowName, DWORD
dwStyle,
const
RECT& rect, CWnd* pParentWnd, UINT nID, CFile*
pPersist = NULL,
BOOL bStorage = FALSE, BSTR bstrLicKey = NULL)
{
return
CreateControl(GetClsidO, IpszWindowName, dwStyle,
rect, pParentWnd, nID, pPersist, bStorage,
bstrLicKey);
}
//====== Методы, экспонируемые элементом ActiveX
public:
void
SetFillColor(unsigned long newValue);
unsigned long
GetFillColor();
void
GetLightParams(long* pPos);
void
SetLightParam(short Ip, long nPos);
void
ReadData();
void
SetFillMode(DWORD mode);
void
GetFillMode(DWORD* pMode);
void
GetQuad(BOOL* bQuad);
void
SetQuad(BOOL bQuad);
};
Самым важным моментом в процедуре вставки класса
является правильное задание CLSID того класса
OpenGL, который был зарегистрирован в
операционной системе при создании DLL-сервера,
то есть нашего элемента ActiveX. He пытайтесь
сравнивать те цифры, которые приведены в книге,
с теми, которые были приведены в ней же до этого
момента, так как в процессе отладки пришлось не
раз менять как классы, так и целиком приложения.
Мне не хочется отслеживать эти жуткие номера.
Если вы хотите вставить правильные цифры, то
должны взять их из вашей версии
предыдущего приложения ATLGL. Например, откройте
файл ATLGL.IDL и возьмите оттуда CLSID для
ко-класса OpenGL, то есть найдите такой фрагмент
этого файла:
[
uuid(519D9ED8-BC46-4367-9CCO-498140F39416),
helpstring("OpenGL
Class") ]
coclass
OpenGL
{
[default] interface
IOpenGL;
[default, source] dispinterface
_IOpenGLEvents;
};
И скопируйте первую
строку
uuid(519D9ED8-BC46-4367-9CCO-498140F39416),
но с вашими цифрами и вставьте ее в
качестве комментария в файл OpenGLh
нового проекта TestGL. Затем аккуратно, соблюдая
формат, принятый для структуры CLSID, перенесите
только цифры в поля статической структуры clsid,
которую вы видите в методе GetClsid
класса-оболочки. Цифры должны быть взяты из
принесенной строки, но их надо отформатировать
(разбить) по-другому принципу. Например, для
нашего случая правильным будет такое тело метода
GetClsid:
CLSID const& GetClsid()
{
// Следующая строка взята из файла ATLGL.IDL
// 519D9ED8-BC46-4367-9CCO-498140F39416
static
CLSID const clsid =
{
//======== Эти цифры взяты из файла ATLGL.IDL
0x519d9ed8, 0xbc46, 0x4367,
{ 0х9с, 0xc0, 0x49, 0x81, 0x40, 0xf3, 0x94, 0x16
} ) ;
return
clsid;
}
Кроме этого важного фрагмента в новом классе
объявлены два совмещенных метода Create, каждый
из которых умеет создавать окно внедренного
элемента ActiveX с учетом особенностей стиля
окна (см. справку по CWnd: :CreateControl).
Затем в классе-оболочке должны быть представлены
суррогаты всех методов, экспонируемых классом
OpenGL COM DLL-сервера ATLGL.DLL. В том, что вы
не полностью приводите тела методов сервера,
иначе это был бы абсурд, хотя и так близко к
этому, можно убедиться, просмотрев на редкость
унылые коды реализации класса-оболочки, которые
необходимо вставить в файл OpenGLcpp. Утешает
мысль, что в исправной Studio.Net эти коды не
придется создавать и редактировать вручную:
#include
"stdafx.h"
#include
"opengl.h"
IMPLEMENT_DYNCREATE(COpenGL, CWnd)
//====== Стандартное свойство реализовано
//====== в виде пары методов Get/Set
void
COpenGL::SetFillColor(unsigned long
newValue)
{
static
BYTE parms[] =
VTS_I4; InvokeHelper(0xfffffe02,
DISPATCH_PROPERTYPUT,VT_EMPTY,
NULL, parms, newValue);
}
//======
Стандартное свойство
unsigned long
COpenGL::GetFillColor0 {
unsigned long
result;
InvokeHelper (Oxfffffe02, DISPATCH_PROPERTYGET,
VT_I4, (void4)&result, NULL);
return
result;
}
//======
Наши методы сервера
void
COpenGL::GetLightParams(long* pPos)
{
static
BYTE parms[] = VTS_PI4;
InvokeHelper (Oxl, DISPATCH_METHOD, VT_EMPTY,
NULL,
parms, pPos);
}
void
COpenGL: : SetLightParam (short lp, long nPos)
{
static
BYTE parms [ ] = VTS 12 VTS 14;
InvokeHelper{0x2, DISPATCH_METHOD, VT_EMPTY,
NULL,
parms, lp, nPos);
}
void
COpenGL::ReadData()
InvokeHelper(0x3, DISPATCH_METHOD, VT_EMPTY, 0,
0) ;
void
COpenGL::GetFillMode(DWORD* pMode)
static
BYTE jparms[] =
VTS_PI4; InvokeHelper (0x4, DISPATCH_METHOD,
VT_EMPTY, NULL,
parms, pMode);
}
void
COpenGL::SetFillMode(DWORD nMode)
static
BYTE parms[] =
VTS_I4;
InvokeHelper(0x5, DISPATCH_METHOD, VT_EMPTY,
NULL, parms, nMode);
void
COpenGL::GetQuad(BOOL* bQuad)
static
BYTE parms[] =
VTS_PI4;
InvokeHelper(0x6, DISPATCH_METHOD, VT_EMPTY,
NULL, parms, bQuad);
void
COpenGL::SetQuad(BOOL bQuad)
static
BYTE parms[] =
VTS_I4;
InvokeHelper (0x7,
DISPATCH_METHOD, VT_EMPTY, NULL, parms, bQuad);
}
Затем подключите оба новых файла к проекту
Project > Add Existing Item. |