Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«Π‘ΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ БОМ. Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° программиста». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 85

Автор Π”ΠΎΠ½Π°Π»ΡŒΠ΄ Бокс

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 ΠΏΡ€ΠΈΡˆΠ»ΠΎΡΡŒ Π±Ρ‹ Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΠΊΠΎΠ΄: