Иллюстрированный самоучитель по Visual Studio.Net

         

Класс-оболочка


Обычно при создании приложения-контейнера для элемента 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.




    Содержание раздела