[ Pobierz całość w formacie PDF ]
.Klikaj¹cprzycisk „Detailed Info” (btnDetailedZodiac), spowodujemy wykonanienastêpuj¹cej funkcji zdarzeniowej:Wydruk 12.16.Uzyskiwanie informacji o znaku zodiaku za pomoc¹ klasycznegointerfejsuvoid __fastcall TMainForm::btnDetailedZodiacClick(TObject *Sender){TDateTime TheDate(FCalendar->Date);unsigned short year = 0;unsigned short month = 0;unsigned short day = 0;TheDate.DecodeDate(&year, &month, &day);// ukryte wywo³anie QueryInterface():IDetailedZodiacPtr DetailedZodiac = FZodiac;if (!chkAsync->Checked){TDetailedZodiacSignImpl DetailedSign;OLECHECK(DetailedZodiac->GetDetailedZodiacSign(day, month, &DetailedSign));memLog->Lines->Add(_T("Zodiac detailed information:"));memLog->Lines->Add(_T(" Sign = ") + AnsiString(DetailedSign.Sign));memLog->Lines->Add(_T(" House = ") + IntToStr(DetailedSign.House));memLog->Lines->Add(_T(" Type = ") + AnsiString(DetailedSign.Element));memLog->Lines->Add(_T(" Planet = ") + AnsiString(DetailedSign.Planet));memLog->Lines->Add(_T(" Details = ") + AnsiString(DetailedSign.Details));memLog->Lines->Add(_T(" Tip = ") + AnsiString(DetailedSign.Advice));memLog->Lines->Add(_T(""));memLog->Lines->Add(_T(""));}else{OLECHECK(DetailedZodiac->GetDetailedZodiacSignAsync(day, month));}}Funkcja btnDetailedZodiacClick() jest bardzo podobna do prezentowanej wczeœniejfunkcji btnZodiacClick; najistotniejsze ró¿nice zaznaczyliœmy czcionk¹wyt³uszczon¹.Tworzenie ujœcia zdarzeñ zbudowanego na klasycznym interfejsiePonownie potrzebny jest obiekt COM po stronie klienta, tym razem w celuimplementacji interfejsu IDetailedZodiacEvents.Jego konstrukcja staje siêzadaniem wzglêdnie nieskomplikowanym dziêki bibliotece ATL – skonstruujemymianowicie szablon, na bazie którego w prosty sposób definiowaæ mo¿na bêdzieklasy implementuj¹ce ró¿ne rodzaje ujœæ zdarzeñ.Kod Ÿród³owy tego szablonu,prezentowany na wydruku 12.17, znajduje siê tak¿e w pliku CustomSinks.h naza³¹czonej p³ycie CD-ROM.Wydruk 12.17.TCustomSink – szablon bazowy do definiowania w³asnych ujœæzdarzeñtemplateclass TCustomSink : public Base{private:CComPtr m_ptrSender; // generator zdarzeniaDWORD m_dwCookie; // cookie po³¹czeniowepublic:TCustomSink() :m_dwCookie(0) { }virtual ~TCustomSink() { Disconnect(); }// iplementacja interfejsu IUnknown:STDMETHOD_(ULONG, AddRef)() { return 1; }STDMETHOD_(ULONG, Release)() { return 1; }STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject){ return _InternalQueryInterface(iid, ppvObject); }public:// metody realizuj¹ce po³¹czenie i roz³aczenie z serweremHRESULT __fastcall Connect(IUnknown* pSender){HRESULT hr = S_FALSE;if (pSender != m_ptrSender){m_ptrSender = pSender;if (m_ptrSender != NULL){CComPtr ptrUnk;QueryInterface(IID_IUnknown, reinterpret_cast(&ptrUnk));hr = AtlAdvise(m_ptrSender, ptrUnk, *piid, &m_dwCookie);}}return hr;}HRESULT __fastcall Disconnect(){HRESULT hr = S_FALSE;if ( (m_ptrSender != NULL) &&(0 != m_dwCookie) ){hr = AtlUnadvise(m_ptrSender, *piid, m_dwCookie);m_dwCookie = 0;m_ptrSender = NULL;}return hr;}};Jak widaæ, prezentowany szablon implementuje interfejs IUnknown, przy czym jegonajbardziej skomplikowana (zazwyczaj) metoda implementowana jest za pomoc¹metody InternalQueryInterface() klasy CComObjectRoot, dlatego te¿ pierwszy zargumentów szablonu (Base) musi byæ klas¹ CComObjectRoot lub jej klas¹pochodn¹.Innym interesuj¹cym fragmentem powy¿szego wydruku s¹ metody Connect() iDisconnect() odpowiedzialne za nawi¹zanie i zakoñczenie po³¹czenia ujœciazdarzeñ z serwerem.Do ich implementacji u¿yliœmy mianowicie funkcjiAtlAdvise() i AtlUnadvise() pochodz¹cych z biblioteki ATL.Przepis na definiowanie w³asnej klasy reprezentuj¹cej ujœcie zdarzeñ na bazieszablonu TCustomSink jest nastêpuj¹cy:Nale¿y zdefiniowaæ obiekt COM na bazie klas CComObjectRootEx (alboCComObjectRoot) oraz CComCoClass.Nale¿y uczyniæ implementowany interfejs zdarzenia kolejn¹ klas¹ bazow¹ obiektui oczywiœcie stworzyæ implementacjê metod tego interfejsu.Zdefiniowaæ typ w³asnego ujœcia zdarzeñ, na przyk³ad:typedef TCustomSink TMyCreatableSink;Ilustracj¹ powy¿szego przepisu jest wydruk 12.18, na którym przedstawiono klasêTDetailedZodiacSinkImpl implementuj¹c¹ ujœcie zdarzeñ ZodiacCustomSink dlainterfejsu IDetailedZodiacEvents.Zawartoœæ tego wydruku znajduje siê w plikuZodiacCustomSink.h na za³¹czonej p³ycie CD-ROM.Wydruk 12.18.Deklaracja klasy implementuj¹cej ujœcie zdarzeñ dla interfejsuIDetailedZodiacEvents#if !defined(ZODIACCUSTOMSINK_H__)#define ZODIACCUSTOMSINK_H__#include#include#include#include#include#include "CustomSinks.h"#include "ZodiacServer_TLB.h"typedef void __fastcall (__closure * TDetailedZodiacSignReadyEvent)(TDetailedZodiacSign& DetailedSign);//---------------------------------------------------------------------------// Klasa implementuj¹c¹ interfejs IDetailedZodiacEventsclass ATL_NO_VTABLE TDetailedZodiacSinkImpl :public CComObjectRootEx,public CComCoClass,public IDetailedZodiacEvents{public:TDetailedZodiacSinkImpl() :FOnDetailedZodiacSign(NULL){}DECLARE_THREADING_MODEL(otApartment);BEGIN_COM_MAP(TDetailedZodiacSinkImpl)COM_INTERFACE_ENTRY(IDetailedZodiacEvents)END_COM_MAP()protected:// WskaŸnik funkcji zdarzeniowejTDetailedZodiacSignReadyEvent FOnDetailedZodiacSign;public:__property TDetailedZodiacSignReadyEvent OnDetailedZodiacSign ={ read = FOnDetailedZodiacSign, write = FOnDetailedZodiacSign };// IDetailedZodiacEventspublic:STDMETHOD(OnDetailedZodiacSignReady(TDetailedZodiacSign* DetailedSign)){if (FOnDetailedZodiacSign != NULL)FOnDetailedZodiacSign(*DetailedSign);return S_OK;}};typedef TCustomSinkTZodiacCustomSink;#endif //ZODIACCUSTOMSINK_H__Czytelnicy spostrzegli zapewne, i¿ do budowy aplikacji klienta u¿yliœmy tychsamych klas i makr biblioteki ATL, z których korzystaliœmy ju¿ przy budowieserwera.Jest tu jednak pewna ró¿nica – nie jest konieczne tworzenie mapy COM,bowiem aplikacja klienta nie bêdzie tworzyæ egzemplarzy obiektu COM; z tegosamego powodu nieistotny jest CLSID tego¿ obiektu, dlatego te¿ zamiast niegou¿yliœmy zerowego identyfikatora CLSID_NULL.Maj¹c ju¿ zdefiniowan¹ klasê TZodiacCustomSink, nale¿y zrobiæ z niej u¿ytek wprojekcie aplikacji – klienta.Podobnie jak w przypadku klasy TZodiacSink,nale¿y najpierw dodaæ odpowiednie pole do formularza g³Ã³wnego:private:…TZodiacCustomSink FZodiacCustomSink;Nastêpnie nale¿y zdefiniowaæ metodê formularza, obs³uguj¹c¹ zdarzenie:OnDetailedZodiacSignReady:void __fastcall TMainForm::OnDetailedZodiacSignReady(TDetailedZodiacSign& DetailedSign){memLog->Lines->Add(_T("Zodiac detailed information (ASYNCHRONOUS):"));memLog->Lines->Add(_T(" Sign = ") + AnsiString(DetailedSign.Sign));memLog->Lines->Add(_T(" House = ") + IntToStr(DetailedSign
[ Pobierz całość w formacie PDF ]
Darmowy hosting zapewnia PRV.PL