GIP(IPoint) m_gipTopLeft;
// GIT cookie – top/left
// «закладка» GIT для верхнего/левого элемента
GIP(IPoint) m_gipBottomRight;
// GIT cookie – bottom/right
// «закладка» GIT для нижнего/правого элемента
:
:
:
}
Для инициализации элемента
SafeRect::SafeRect(void) : m_cRef (0), m_pUnkFTM(0) {
IPoint *pPoint = 0;
// create instance of class Point
// создаем экземпляр класса Point
HRESULT hr = CoCreateInstance(CLSID_Point, 0, CLSCTX_INPROC, IID_Ipoint, (void**)&pPoint);
assert (SUCCEEDED(hr));
// register interface pointer in GIT
// регистрируем интерфейсный указатель в GIT
hr = m_gipTopLeft.Globalize(pPoint);
assert (SUCCEEDED(hr));
pPoint->Release();
// reference is now held in GIT
// теперь ссыпка хранится в GIT
// create instance of class Point
// создаем экземпляр класса Point
hr = CoCreateInstance(CLSID_Point, 0, CLSCTX_INPROC, IID_Iроint, (void**) &рРоint);
assert(SUCCEEDED(hr));
// register interface pointer in GIT
// регистрируем интерфейсный указатель в GIT
hr = m_gipBottomRight.Globalize(pPoint);
assert (SUCCEEDED (hr));
pPoint->Release();
// reference is now held in GIT
// теперь ссылка хранится в GIT
}
Те методы, которым нужен доступ к глобализованным указателям, могут импортировать локальную копию посредством метода
STDMETHODIMP SafeRect::get_Top(long *pVal) {
IPoint *pPoint = 0;
// local imported pointer
// локальный импортированный указатель
HRESULT hr = m_gipTopLeft.Localize(&pPoint);
if (SUCCEEDED(hr)){
long x;
hr = pPoint->get_Coords(&x, pVal);
pPoint->Release(); }
return hr;
}
Отметим, что в силу применения маршалера свободной поточной обработки (
Предыдущий фрагмент кода может быть автоматизирован еще больше. Поскольку большинство вызовов методов в классе
template
Itf *m_pItf;
// temp imported pointer
// временный импортированный указатель
// prevent misuse
// предотвращаем неверное использование
LocalInterfacePointer(const LocalInterfacePointer&);
operator = (const LocalInterfacePointer&);
public:
LocalInterfacePointer(const GlobalInterfacePointer
LocalInterfacePointer(DWORD dwCookie, HRESULT& hr) { assert(g_pGIT != 0);
hr = g_pGIT->GetInterfaceFromGlobal(dwCookie, *piid, (void**)&m_pItf); }
~LocalInterfacePointer(void) { if (m_pItf) m_pItf->Release(); }
class SafeItf : public Itf { STDMETHOD_(ULONG, AddRef) (void) = 0;
// hide
// скрытый STDMETHOD_(ULONG, Release)(void) = 0;
// hide
// скрытый
};
SafeItf *GetInterface(void) const { return (SafeItf*) m_pItf; }
SafeItf *operator ->(void) const { assert(m_pItf != 0);
return GetInterface();
}
};
#def1ne LIP(Itf) LocalInterfacePointer
С получением этого второго класса C++ обработка импортированных указателей становится намного проще:
STDMETHODIMP SafeRect::get_Area(long *pn) {
long top, left, bottom, right;
HRESULT hr, hr2;
// import pointers
// импортируем указатели
LIP(IPoint) lipTopLeft(m_gipTopLeft, hr);
LIP(IPoint) lipBottomRight(m_gipBottomRight, hr2);
assert(SUCCEEDED(hr) && SUCCEEDED(hr2));
// use temp tocal pointers
// используем временные локальные указатели
hr = lipTopLeft->GetCoords(&left, ⊤);
hr2 = lipBottomRight->GetCoords(&right, ⊥);
assert(SUCCEEDED(hr) && SUCCEEDED(hr2));
*pn = (right – left) * (bottom – top); return S_OK;
// LocalInterfacePointer auto-releases temp ptrs.
// LocalInterfacePointer сам освобождает
// временные указатели
}
Макросы
Где мы находимся?