Модель программирования Component Object Model. Разработка COM-сервера, страница 24

В VBScrit нет строгого контроля соответствия типов и многие типы C++ ему неизвестны. Интерфейс IDispatch служит посредником в разговоре двух Microsoft-созданий. Теперь программа на VBScrit может добраться до метода SomeMethod, выполнив длинную цепь вызовов. Сначала она должна получить указатель на интерфейс IDispatch, затем с его помощью узнать индекс желаемого метода (типа DISPID, на сей раз не 128-битного). Затем вызвать метод Invoke того же интерфейса диспетчеризации, подав на вход 8 параметров, смысл которых примерно такой: (Последущий текст воспринимайте очень серьезно, так как он взят прямо из справки IDispatch::Invoke.)

¨  вызови пятую функцию из vtable, так как ты сказал, что ее зовут SomeMethod,

¨  возьми пока неиспользуемый параметр,

¨  возьми 32-битный описатель местности (LCID),

¨  возьми флаг DISPATCH_METHOD |  DISPATCH_PROPERTYGET, описывающий суть того, что я прошу у пятой функции,

¨  возьми адрес структуры DISPPARAMS, в которую я завернул: массив аргументов, массив индексов (DISPID) для них и числа, описывающие размеры массивов,

¨  возьми адрес структуры VARIANT (из 49 полей, правда 47 из них union), в которую она (пятая функция) пусть положит ответ, если в 4 параметре (флаге) я указал, что он мне нужен,

¨  возьми адрес структуры EXCEPINFO, в которую система, если что случится (ну, она меня не поймет, или что другое) пусть запишет причину неприятности,

¨  возьми адрес переменной, в которой дай мне назад индекс первого аргумента в массиве неприятностей, так как аргументы там хранятся в обратном порядке, а мне нужна ошибка с самым высоким индексом. Но если не вернешь DISP_E_TYPEMISMATCH или DISP_E_PARAMNOTFOUND в HRESULT'е, то ничего не клади в эту переменную.

Обратите внимание на механизм реализации свойств в ATL. Он использует одну переменную и два метода (типа get, set). Интерфейс IOpenGL предоставляет своим пользователям два одноименных метода FillColor. Первый метод позволяет пользователю изменить (propput) стандартное (stock property) свойство: цвет заливки. Второй — узнать (propget) текущее значение этого свойства. Этот интерфейс был вставлен мастером потому, что при создании элемента мы указали на необходимость введения в него одного из стандартных свойств. С этой же целью мастер ввел в состав класса переменную:

OLE_COLOR m_clrFillColor;

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

COpenGL()

{

m_clrFillColor = RGB(255,230,255);

}

Но этого мало. Для того, чтобы увидеть результат надо изменить коды функции рисования, которую вы найдете в том же файле OpenGL.h.

Вступив в царство ATL, вы должны отречься от многих привычек, приобретенных в MFC. Вы уже заметили, что мы теперь вместо char* или CString пользуемся OLESTR, а вместо COLORREF — OLE_COLOR. Это еще не так отвлекает, но вот теперь мы должны рисовать без помощи привычного класса CDC и вернуться к описателю HDC контекста устройства, которым мы пользовались при разработке традиционного Windows-приложения на основе функций API. Надо также привыкнуть к тому, что описатель HDC hdcDraw упрятан в структуру типа ATL_DRAWINFO, ссылку на которую мы получаем в параметре метода OnDraw класса CComControl.

Напомню, что вся функциональность класса CComControl унаследована нашим классом COpenGL, который, кроме него, имеет еще 17 родителей. Состав полей структуры ATL_DRAWINFO мы не будем приводить здесь, чтобы не усугублять головокружение, а вместо этого предложим убедиться в том, что мы можем влиять на облик COM-объекта.