Введение методов в интерфейс IOpenGL
На этом этапе важно решить, какие данные (свойства) и методы класса будут экспонироваться СОМ-объектом, а какие останутся в качестве служебных, для внутреннего пользования. Те методы и свойства, которые будут экспонированы, должны быть соответствующим образом отражены в IDL-файле. Те, которые нужны только нам, останутся внутри сервера. Для примера введем в число экспонируемых методов функцию GetLightParams, которая определяет действующие параметры освещения.
- Поставьте фокус на строку с именем интерфейса lOpenGL в окне CLassView и вызовите контекстное меню.
- Выберите команду Add › Add Method. В окне мастера Add Method Wizard введите в поле Method Name имя метода GetLightParams. В поле Parameter Name введите имя параметра pPos, в поле Parameter Type: – тип параметра int*, задайте атрибут параметра, установив флажок out, и нажмите кнопку Add.
- Нажмите кнопку Finish.
Проанализируйте изменения, которые появились в IDL-файле, в файле OpenGLh и в файле OpenGLcpp. В первом из перечисленных файлов появилось новое, уточненное описание метода интерфейса:
interface lOpenGL: IDispatch { [propput, bindable, requestedit, id(DISPID_FILLCOLOR)] HRESULT FillColor([in]OLE_COLOR clr); [propget, bindable, requestedit, id(DISPID_FILLCOLOR)] HRESULT FillColor([out, retval] OLE_COLOR* pclr); [id(l), helpstring("method GetLightParams")] HRESULT GetLightParams([out] int* pPos); };
В файле заголовков появилась строка декларации метода ко-класса, который реализует функциональность интерфейса:
STDMETHODIMP GetLightParams(int* pPos);
И, наконец, в файле реализации ко-класса появилась стартовая заготовка тела метода:
STDMETHODIMP COpenGL::GetLightParams(int *pPos) { // TODO: Add your implementation code here return S_OK; }
Повторите описанные действия и введите в интерфейс еще один метод SetLightParam, который изменяет один из параметров освещения сцены OpenGL. При задании параметров этого метода добейтесь такого описания в окне Parameter List:
[in] short lp [in] int nPos;
Введите в состав интерфейса еще один метод ReadData, на сей раз без параметров. Он будет реагировать на кнопку и производить чтение файла с данными о новом графике. Для управления обликом поверхности графика нам понадобятся две пары методов типа get-set. Введите в интерфейс следующие методы:
- GetFillMode с параметром [out] DWORD* pMode;
- SetFillMode с параметром [in] DWORD nMode;
- GetQuad с параметром [out] BOOL* bQuad;
- SetQuad с параметром [in] BOOL bQuad.
Найдите новые методы в IDL-файле и убедитесь, что мастер автоматически пронумеровал методы (1.2,…), присвоив им индексы типа DISPID:
[id(l), helpstring("method GetLightParams")] HRESULT GetLightParams([out] int* pPos); [id(2), helpstring("method SetLightParam")] HRESULT SetLightParam([in] short Ip, [in] int nPos); [id(3), helpstring("method ReadData")] HRESULT ReadData(void); [id(4), helpstring("method GetFillMode")] HRESULT GetFillMode([out] DWORD* pMode); [id(5), helpstring("method SetFillMode")] HRESULT SetFillMode([in] DWORD nMode); [id(6), helpstring("method GetQuad")] HRESULT GetQuad([out] BOOL* bQuad); [id(7), helpstring("method SetQuad")] HRESULT SetQuad([in] BOOL bQuad);
С помощью этих индексов методы будут вызываться клиентами, получившими указатель на интерфейс диспетчеризации IDispatch. Мы уже обсуждали способ, который используется при вызове методов по индексам DISPID. Непосредственный вызов производит метод IDispatch::invoke. Тот факт, что наш объект поддерживает IDispatch, мы определили при создании ATL-заготовки. Если вы не забыли, то мы тогда установили переключатель типа интерфейса в положение Dual. Это означает, что объект будет раскрывать свои методы как с помощью vtable, так и с помощью IDispatch. Некоторые детали этого процесса обсуждались в предыдущем уроке.