class Surfboard : public ISurfboard,
public IHazardousDevice,
public ISharkBait,
public IConnectionPointContainer {
LONG m_cRef; // Π‘ΠM reference count
// ΡΡΠ΅ΡΡΠΈΠΊ ΡΡΡΠ»ΠΎΠΊ Π‘ΠΠ
// Surfboards don't support multiple outbound interfaces
// of a given type, so it simply declares single pointers
// of each possible type of callback interface
// Surfboard Π½Π΅ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅Ρ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΠΊΡΠΏΠΎΡΡΠΈΡΡΠ΅ΠΌΡΡ
// ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ² Π·Π°Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΡΠΈΠΏΠ°, ΠΏΠΎΡΡΠΎΠΌΡ ΠΎΠ½ ΠΏΡΠΎΡΡΠΎ
// ΠΎΠ±ΡΡΠ²Π»ΡΠ΅Ρ ΠΎΠ΄ΠΈΠ½ΠΎΡΠ½ΡΠ΅ ΡΠΊΠ°Π·Π°ΡΠ΅Π»ΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΠ³ΠΎ
// ΡΠΈΠΏΠ° ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ° ΠΎΠ±ΡΠ°ΡΠ½ΠΎΠ³ΠΎ Π²ΡΠ·ΠΎΠ²Π°
IShutdownNotify *m_pShutdownNotify;
ISurfboardUser *m_pSurfer;
// to deal with identity relationship of IConnectionPoint,
// define an IShutdownNotify-specific nested class + member
// Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ ΠΎΡΠ½ΠΎΡΠ΅Π½ΠΈΠ΅ΠΌ ΡΠΎΠΆΠ΄Π΅ΡΡΠ²Π΅Π½Π½ΠΎΡΡΠΈ
// IConnectionPoint, ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅ΠΌ ΡΠΏΠ΅ΡΠΈΡΠΈΡΠ΅ΡΠΊΠΈΠΉ Π΄Π»Ρ
// IShutdownNotify Π²Π»ΠΎΠΆΠ΅Π½Π½ΡΠΉ ΠΊΠ»Π°ΡΡ+ΡΠ»Π΅Π½
class XCPShutdownNotify : public IConnectionPoint {
Surfboard *This(void);
// use fixed offset
// ΠΈΡΠΏΠΎΠΏΡΠ·ΡΠ΅ΠΌ ΠΏΠΎΡΡΠΎΡΠ½Π½ΠΎΠ΅ ΡΠΌΠ΅ΡΠ΅Π½ΠΈΠ΅
// IUnknown methods...
// ΠΌΠ΅ΡΠΎΠ΄Ρ IUnknown...
// IConnectionPoint methods...
// ΠΌΠ΅ΡΠΎΠ΄Ρ IConnectionPoint...
} m_xcpShutdownNotify;
// define an ISurfboardUser-specific nested class + member
// ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅ΠΌ ΡΠΏΠ΅ΡΠΈΡΠΈΡΠ΅ΡΠΊΠΈΠΉ Π΄Π»Ρ IShutdownNotify Π²Π»ΠΎΠΆΠ΅Π½Π½ΡΠΉ ΠΊΠ»Π°ΡΡ+ΡΠ»Π΅Π½
class XCPSurfboardUser : public IConnectionPoint {
Surfboard *This(void);
// use fixed offset
// ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ ΠΏΠΎΡΡΠΎΡΠ½Π½ΠΎΠ΅ ΡΠΌΠ΅ΡΠ΅Π½ΠΈΠ΅
// IUnknown methods...
// ΠΌΠ΅ΡΠΎΠ΄Ρ IUnknown...
// IConnectionPoint methods...
// ΠΌΠ΅ΡΠΎΠ΄Ρ IConnectionPoint...
} m_xcpSurfboardUser;
// IUnknown methods...
// ΠΌΠ΅ΡΠΎΠ΄Ρ IUnknown...
// ISurfboard methods...
// ΠΌΠ΅ΡΠΎΠ΄Ρ ISurfboard...
// IHazardousDevice methods...
// ΠΌΠ΅ΡΠΎΠ΄Ρ IHazardousDevice...
// ISharkBait methods...
// ΠΌΠ΅ΡΠΎΠ΄Ρ ISharkBait...
// IConnectionPointContainer methods...
// ΠΌΠ΅ΡΠΎΠ΄Ρ IConnectionPointContainer...
};
Π‘Π»Π΅Π΄ΡΠ΅Ρ ΡΠΊΠ°Π·Π°ΡΡ, ΡΡΠΎ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΡ ΠΊΠ»Π°ΡΡΠ° Surfboard Π±ΡΠ΄ΡΡ ΠΈΠΌΠ΅ΡΡ Π΄Π²Π΅ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠ΅ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ IConnectionPoint, ΠΎΠ΄Π½Π° ΠΈΠ· ΠΊΠΎΡΠΎΡΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ Π΄Π»Ρ ΠΏΡΠΈΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ² ΠΎΠ±ΡΠ°ΡΠ½ΠΎΠ³ΠΎ Π²ΡΠ·ΠΎΠ²Π° IShutdownNotify, Π° Π²ΡΠΎΡΠ°Ρ β Π΄Π»Ρ ΠΏΡΠΈΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ² ISurfboardUser. ΠΡΠΈ Π΄Π²Π΅ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΡΠ°Π·Π΄Π΅Π»Π΅Π½Ρ Π½Π° ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠ΅ ΠΊΠ»Π°ΡΡΡ C++, ΡΡΠΎ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ IConnectionPoint ΠΈΠΌΠ΅ΡΡ ΡΠ²ΠΎΠΈ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΡΠ΅ ΡΠ½ΠΈΠΊΠ°Π»ΡΠ½ΡΠ΅ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ IUnknown ΠΈ IConnectionPoint. Π ΡΠ°ΡΡΠ½ΠΎΡΡΠΈ, ΠΌΠΎΠΆΠ΅Ρ ΠΈΠΌΠ΅ΡΡΡΡ ΡΡΠΈ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΡ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ QueryInterface ΡΠΎ ΡΠ²ΠΎΠΈΠΌΠΈ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΡΠΌΠΈ Π½Π°Π±ΠΎΡΠ°ΠΌΠΈ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ½ΡΡ ΡΠΊΠ°Π·Π°ΡΠ΅Π»Π΅ΠΉ, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΌΠΎΠ³ΡΡ Π±ΡΡΡ Π²ΡΠ΄Π΅Π»Π΅Π½Ρ Π΄Π»Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΡΡΠ΅Ρ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΡ Π‘ΠΠ-ΠΊΠΎΠΏΠΈΠΉ.
ΠΠ· ΠΏΡΠΈΠ²Π΅Π΄Π΅Π½Π½ΠΎΠ³ΠΎ Π²ΡΡΠ΅ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΡ ΠΊΠ»Π°ΡΡΠ° ΡΠ»Π΅Π΄ΡΠ΅Ρ ΡΠ°ΠΊΠ°Ρ QueryInterface-peaΠ»ΠΈΠ·Π°ΡΠΈΡ ΠΎΡΠ½ΠΎΠ²Π½ΠΎΠ³ΠΎ ΠΊΠ»Π°ΡΡΠ° Surfboard:
STDMETHODIMP Surfboard::QueryInterface(REFIID riid, void**ppv)
{
if (riid == IID_IUnknown || riid == IID_ISurfboard)
*ppv = static_cast<ISurfboard*>(this);
else if (riid == IID_IHazardousDevice)
*ppv = static_cast< IHazardousDevice *>(this);
else if (riid == IID_ISharkBait)
*ppv = static_cast<ISharkBait *>(this);
else if (riid == IID_IConnectionPointContainer)
*ppv = static_cast<IConnectionPointContainer *>(this);
else
return (*ppv = 0), E_NOINTERFACE;
((IUnknown*)*ppv)->AddRef();
return S_OK;
}
ΠΡΠΌΠ΅ΡΠΈΠΌ, ΡΡΠΎ Π΄ΠΎΡΡΡΠΏ ΠΊ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΡ IConnectionPoint Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΠΎΡΡΡΠ΅ΡΡΠ²Π»Π΅Π½ ΡΠ΅ΡΠ΅Π· ΡΡΡ Π³Π»Π°Π²Π½ΡΡ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ QueryInterface. ΠΠ°ΠΆΠ΄ΡΠΉ ΠΈΠ· ΠΌΠ΅ΡΠΎΠ΄ΠΎΠ² QueryInterface Π²Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ³ΠΎ ΠΊΠ»Π°ΡΡΠ° Π±ΡΠ΄Π΅Ρ Π²ΡΠ³Π»ΡΠ΄Π΅ΡΡ ΠΏΡΠΈΠΌΠ΅ΡΠ½ΠΎ ΡΠ°ΠΊ:
STDMETHODIMP Surfboard::XCPShutdownNotify::QueryInterface(REFIID riid, void**ppv)
{
if (riid == IID_IUnknown || riid == IID_IConnectionPoint)
*ppv = static_cast<IConnectionPoint *>(this);
else
return (*ppv = 0), E_NOINTERFACE;
((IUnknown*)*ppv)->AddRef();
return S_OK;
}
ΠΡΡ ΠΆΠ΅ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΌΠΎΠΆΠ½ΠΎ Π±ΡΠ»ΠΎ Π±Ρ ΠΏΡΠΈΠΌΠ΅Π½ΠΈΡΡ ΠΈ ΠΊ ΠΊΠ»Π°ΡΡΡ XCPSurfboardUser. ΠΠ΅ΠΆΠ΄Ρ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠΌ Surfboard ΠΈ Π΄Π²ΡΠΌΡ ΠΏΠΎΠ΄ΠΎΠ±ΡΠ΅ΠΊΡΠ°ΠΌΠΈ, ΠΊΠΎΡΠΎΡΡΠ΅ ΡΠ΅Π°Π»ΠΈΠ·ΡΡΡ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ IConnectionPoint Π½Π΅ ΡΡΡΠ΅ΡΡΠ²ΡΠ΅Ρ ΠΈΠ΄Π΅Π½ΡΠΈΡΠ½ΠΎΡΡΠΈ.
ΠΠ»Ρ ΡΠΎΠ³ΠΎ ΡΡΠΎΠ±Ρ ΠΎΠ±ΡΠ΅ΠΊΡ Surfboard Π½Π΅ ΡΠ½ΠΈΡΡΠΎΠΆΠΈΠ» ΡΠ΅Π±Ρ ΡΠ°Π½ΡΡΠ΅ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ, ΠΏΠΎΠ΄ΠΎΠ±ΡΠ΅ΠΊΡΡ Π°Π΄ΠΌΠΈΠ½ΠΈΡΡΡΠ°ΡΠΎΡΠ° ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠΉ ΠΏΡΠΎΡΡΠΎ Π΄Π΅Π»Π΅Π³ΠΈΡΡΡΡ Π²ΡΠ·ΠΎΠ²Ρ ΡΠ²ΠΎΠΈΡ ΠΌΠ΅ΡΠΎΠ΄ΠΎΠ² AddRef ΠΈ Release Π² ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΠΈΠΉ ΠΈΡ ΠΎΠ±ΡΠ΅ΠΊΡ surfboard:
STDMETHODIMP_(ULONG) Surfboard::XCPShutdownNotify::AddRef(void)
{
return This()->AddRef();
/* AddRef containing object */
/* AddRef ΠΎΠ±ΡΠ΅ΠΊΡΠ°-ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΠ° */
}
STDMETHODIMP_(ULONG) Surfboard::XCPShutdownNotify::Release(void)
{
return This()->Release();
/* Release containing object */
/* Release ΠΎΠ±ΡΠ΅ΠΊΡΠ°-ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΠ° */
}
Π ΠΏΡΠΈΠ²Π΅Π΄Π΅Π½Π½ΡΡ Π²ΡΡΠ΅ ΠΌΠ΅ΡΠΎΠ΄Π°Ρ ΠΏΡΠ΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅ΡΡΡ, ΡΡΠΎ ΠΌΠ΅ΡΠΎΠ΄ This Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ ΡΠΊΠ°Π·Π°ΡΠ΅Π»Ρ Π½Π° ΠΎΠ±ΡΠ΅ΠΊΡ-ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅Ρ Surfboard, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡ Π²ΡΡΠΈΡΠ»Π΅Π½ΠΈΠ΅ Π½Π΅ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ ΠΏΠΎΡΡΠΎΡΠ½Π½ΠΎΠ³ΠΎ ΡΠΌΠ΅ΡΠ΅Π½ΠΈΡ.
ΠΠ»ΠΈΠ΅Π½ΡΡ Π½Π°Ρ ΠΎΠ΄ΡΡ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΡ ΠΎΠ±ΡΠ΅ΠΊΡΠ° IConnectionPoint ΠΏΠΎΡΡΠ΅Π΄ΡΡΠ²ΠΎΠΌ Π²ΡΠ·ΠΎΠ²Π° ΠΌΠ΅ΡΠΎΠ΄Π° ΠΎΠ±ΡΠ΅ΠΊΡΠ° FindConnectionPoint, ΠΊΠΎΡΠΎΡΡΠΉ Π΄Π»Ρ ΠΊΠ»Π°ΡΡΠ° Surfboard ΠΌΠΎΠ³ Π±Ρ Π²ΡΠ³Π»ΡΠ΄Π΅ΡΡ ΠΏΡΠΈΠΌΠ΅ΡΠ½ΠΎ ΡΠ°ΠΊ:
STDMETHODIMP Surfboard::FindConnectionPoint(REFIID riid, IConnectionPoint **ppcp)
{
if (riid == IID_IShutdownNotify)
*ppcp = IID_IShutdownNotify;
else if (riid == IID_ISurfboardUser)
*ppcp = &m_xcpSurfboardUser;
else
return (*ppcp = 0), CONNECT_E_NOCONNECTION;
(*ppcp)->AddRef();
return S_OK;
}
ΠΡΠΌΠ΅ΡΠΈΠΌ, ΡΡΠΎ ΠΎΠ±ΡΠ΅ΠΊΡ Π²ΡΠ΄Π°Π΅Ρ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ½ΡΠ΅ ΡΠΊΠ°Π·Π°ΡΠ΅Π»ΠΈ IConnectionPoint ΡΠΎΠ»ΡΠΊΠΎ ΠΏΡΠΈ Π·Π°ΠΏΡΠΎΡΠ΅ ΡΠ΅Ρ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ², Π½Π° ΠΊΠΎΡΠΎΡΡΠ΅ ΠΎΠ½ ΡΠΌΠΎΠΆΠ΅Ρ ΡΠ΄Π΅Π»Π°ΡΡ ΠΎΠ±ΡΠ°ΡΠ½ΡΠΉ Π·Π°ΠΏΡΠΎΡ. ΠΠ΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΡΠΊΠ°Π·Π°ΡΡ ΡΠ°ΠΊΠΆΠ΅ Π½Π° ΠΏΠΎΡΠ°Π·ΠΈΡΠ΅Π»ΡΠ½ΠΎΠ΅ ΡΡ ΠΎΠ΄ΡΡΠ²ΠΎ Ρ Π±ΠΎΠ»ΡΡΠΈΠ½ΡΡΠ²ΠΎΠΌ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ QueryInterface. ΠΡΠ½ΠΎΠ²Π½ΠΎΠ΅ ΡΠ°Π·Π»ΠΈΡΠΈΠ΅ ΡΠΎΡΡΠΎΠΈΡ Π² ΡΠΎΠΌ, ΡΡΠΎ QueryInterface ΠΈΠΌΠ΅Π΅Ρ Π΄Π΅Π»ΠΎ Ρ ΠΈΠΌΠΏΠΎΡΡΠΈΡΡΠ΅ΠΌΡΠΌΠΈ (inbound) ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ°ΠΌΠΈ, Π² ΡΠΎ Π²ΡΠ΅ΠΌΡ ΠΊΠ°ΠΊ FindConnectionPoint β Ρ ΡΠΊΡΠΏΠΎΡΡΠΈΡΡΠ΅ΠΌΡΠΌΠΈ (outbound) ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ°ΠΌΠΈ.
ΠΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΠΌΠ΅ΡΠΎΠ΄ IConnectionPoint::Advise ΠΏΡΠΈΠ½ΠΈΠΌΠ°Π΅Ρ ΡΠΎΠ»ΡΠΊΠΎ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ IUnknown, ΡΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ ΡΠΈΠΏΠΈΠ·ΠΈΡΠΎΠ²Π°Π½Π½ΡΠΉ ΠΊΠ°ΠΊ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ½ΡΠΉ ΡΠΊΠ°Π·Π°ΡΠ΅Π»Ρ ΠΎΠ±ΡΠ°ΡΠ½ΠΎΠ³ΠΎ Π²ΡΠ·ΠΎΠ²Π°[1], ΡΠΎ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ Advise Π΄ΠΎΠ»ΠΆΠ½Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ QueryInterface Π΄Π»Ρ ΡΠΎΠ³ΠΎ, ΡΡΠΎΠ±Ρ ΠΏΡΠΈΠ²ΡΠ·Π°ΡΡ ΡΠΊΠ°Π·Π°ΡΠ΅Π»Ρ ΠΎΠ±ΡΠ°ΡΠ½ΠΎΠ³ΠΎ Π²ΡΠ·ΠΎΠ²Π° ΠΊ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠ΅ΠΌΡ ΡΠΈΠΏΡ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ°:
STDMETHODIMP Surfboard::XCPShutdownNotify::Advise(IUnknown *pUnk, DWORD *pdwCookie)
{
assert (pdwCookie && pUnk);
*pdwCookie = 0;
if (This()->m_pShutdownNotify) // already have one
// ΡΠΆΠ΅ ΠΈΠΌΠ΅Π΅ΠΌ ΠΎΠ΄ΠΈΠ½
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 ΠΏΡΠΈΡΠ»ΠΎΡΡ Π±Ρ Π½Π°ΠΏΠΈΡΠ°ΡΡ ΡΠ»Π΅Π΄ΡΡΡΠΈΠΉ ΠΊΠΎΠ΄: