В 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-объекта.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.