Читаем Сущность технологии СОМ. Библиотека программиста полностью

// уже имеем один

return CONNECT_E_ADVISELIMIT;

// QueryInterface for correct callback type

// QueryInterface для корректирования типа обратного вызова

HRESULT hr = pUnk->QueryInterface(IID_IShutdownNotify,

(void**)&(This()->m_pShutdownNotify));

if (hr == E_NOINTERFACE)

hr = CONNECT_E_NOCONNECTION;

if (SUCCEEDED(hr)) // make up a meaningful cookie

// готовим значимый маркер

*pdwCookie = DWORD(This()->m_pShutdownNotify);

return hr;

}

Напомним, что QueryInterface неявно вызывает AddRef, что означает следующее: объект Surfboard теперь хранит ссылку обратного вызова, причем она остается легальной за пределами области действия метода Advise. Отметим также, что если объект обратного вызова не реализует соответствующий интерфейс, то результирующий HRESULT преобразуется в CONNECT_E_NOCONNECTION. Если же сбой QueryInterface последовал по какой-либо иной причине, то HRESULT от QueryInterface передается вызывающей программе[2].

Основанный на приведенной выше реализации Advise соответствующий метод Unadvise имеет следующий вид:

STDMETHODIMP Surfboard::XCPShutdownNotify::Unadvise(DWORD dwCookie)

{

// ensure that the cookie corresponds to a valid connection

// убеждаемся, что маркер соответствует допустимому соединению

if (DWORD (This()->m_pShutdownNotify) != dwCookie)

return CONNECT_E_NOCONNECTION;

// release the connection

// освобождаем соединение

This()->m_pShutdownNotify->Release();

This()->m_pShutdownNotify = 0;

return S_OK;

}

В интерфейсе IConnectionPoint имеется три дополнительных вспомогательных метода, два из которых реализуются тривиально:

STDMETHODIMP Surfboard::XCPShutdownNotify::GetConnectionInterface( IID *piid)

{

assert (piid);

// return IID of the interface managed by this subobject

// возвращаем IID интерфейса, управляемого этим подобъектом

*piid = IID_IShutdownNofify;

return S_OK;

}

STDMETHODIMP Surfboard::XCPShutdownNotify::GetConnectionPointContainer(

IConnectionPointContainer **ppcpc)

{

assert(ppcpc);

(*ppcpc = This())->AddRef();

// return containing object

// возвращаем объект-контейнер

return S_OK;

}

Последний из этих трех методов, EnumConnections, позволяет вызывающим программам перенумеровывать соединенные интерфейсы. Данный метод является дополнительным, так что реализации могут законно возвращать E_NOTIMPL.

Для объявления о том, какие из экспортируемых интерфейсов класс реализации поддерживает, в IDL предусмотрен атрибут [source]:

[uuid(315BC280-DEA7-11d0-8C5E-0080C73925BA) ]

coclass Surfboard {

[default] interface ISurfboard;

interface IHazardousDevice;

interface ISharkBait;

[source] interface IShutdownNotify;

[source, default] interface ISurfboardUser;

}

Кроме этого, в СОМ предусмотрено два интерфейса, которые позволяют средам этапа выполнения запрашивать объект самостоятельно (introspectively) возвращать информацию об импортируемых в него и экспортируемых им типах интерфейсов:

[object,uuid(B196B283-BAB4-101A-B69C-00AA00341D07) ]

interface IProvideClassInfo : Unknown {

// return description of object's coclass

// возвращаем описание кокласса объекта

HRESULT GetClassInfo([out] ITypeInfo ** ppTI);

}

[object, uuid(A6BC3AC0-DBAA-11CE-9DE3-00M004BB851) ]

interface IProvideClassInfo2 : IProvideClassInfo {

typedef enum tagGUIDKIND {

GUIDKIND_DEFAULT_SOURCE_DISP_IID = 1

} GUIDKIND;

// return IID of default outbound dispinterface

// возвращаем IID принятого по умолчанию экспортируемого диспинтерфейса

HRESULT GetGUID([in] DWORD dwGuidKind, [out] GUID * pGUID);

}

Оба этих интерфейса весьма просты для реализации:

STDMETHODIMP Surfboard::GetClassInfo(ITypeInfo **ppti)

{

assert(ppti != 0);

ITypeLib *ptl = 0;

HRESULT hr = LoadRegTypeLib(LIBID_BeachLib, 1, 0, 0, &ptl);

if (SUCCEEDED(hr)) {

hr = ptl->GetTypeInfoOfGuid(CLSID_Surfboard, ppti);

ptl->Release();

}

return hr;

}

STDMETHODIMP Surfboard::GetGUID (DWORD dwKind, GUID *pguid)

{

if (dwKind != GUIDKIND_DEFAULT_SOURCE_DISP_IID || !pguid)

return E_INVALIDARG;

// ISurfboardUser must be defined as a dispinterface

// ISurfboardUser должен быть определен как диспинтерфейс

*pguid = IID_ISurfboardUser;

return S_OK;

}

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

Предположим, что интерфейс ISurfboardUser определен как диспинтерфейс следующим образом:

[uuid(315BC28A-DEA7-11d0-8C5E-0080C73925BA)]

dispinterface ISurfboardUser {

methods:

[id(1)] void OnTiltingForward( [in] long nAmount);

[id(2)] void OnTiltingSideways( [in] long nAmount);

}

При программировании на Visual Basic можно объявить переменные, понимающие тип интерфейса обратного вызова, принятый по умолчанию, таким образом:

Dim WithEvents sb as Surfboard

Наличие такого описания переменной дает программистам на Visual Basic возможность писать обработчики событий. Обработчики событий – это функции или подпрограммы, использующие соглашение VariableName_EventName. Например, для обработки события обратного вызова ОпТiltingForward на определенную выше переменную sb программисту Visual Basic пришлось бы написать следующий код:

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных