Presentation is loading. Please wait.

Presentation is loading. Please wait.

제 7장 이벤트.

Similar presentations


Presentation on theme: "제 7장 이벤트."— Presentation transcript:

1 제 7장 이벤트

2 Event 란 무엇인가? 메서드제공 Controller Automation Object 이벤트

3 Event 란 무엇인가? 이벤트란? Automation Object 가 자신에게 어떠한 사건이 발생했다는 사실을 Automation Controller 에게 알려주는 기능 Automation Controller : 자동화 개체에 어떤 작업을 요청하기 위해 매서드 호출 Automation Object: 자동화 컨트롤러에게 어떤 작업을 요청하기 위해서는 이벤트를 발생시켜야 한다.

4 Connection Point 메커니즘 Connection Point 메커니즘 두 부분으로 구성됨 이벤트를 구현하는 메커니즘
Source Interface : 이벤트를 발생시킴. Source Object 는 이를 구현한 개체 = Automation Object Sink Interface : 이벤트를 받아들이는 부분 Sink Object 는 이를 구현한 개체 = Automation Controller 안에서 별도로 생성됨

5 Connection Point 메커니즘 Source Interface Sink Interface
COM 개체 내부에 정의된 인터페이스 Source Interface를 정의하고 있는 COM 개체를 Source Object라 부른다. Fire_ 메서드를 통해 이벤트를 발생시키는 역할을 한다. Sink Interface 클라이언트에 정의된 인터페이스 Sink Interface를 정의하고 있는 Controller를 Sink Object라 부른다. Source Interface를 통해 Fire된 이벤트를 수신하기 위한 인터페이스 Fire_ 메서드에 대응되는 raw_ 메서드를 정의하고 있다. 이벤트를 통하여 Communication하기 위해서는 서로 일치

6 이벤트 발생  수신까지 과정 COM Object는 Source Interface를 통해서 이벤트를 발생시킨다. 즉 Fire_ 메서드를 호출한다. Controller 쪽에서 이를 감지하여 Sink Interface를 생성한다. 생성된 Sink Interface의 인터페이스 포인터가 Source Object로 전달된다. Source Object에서는 전달된 Sink Interface 포인터를 이용하여 Controller에 정의된 대응되는 raw_ 메서드를 호출한다.

7 Sink Interface 생성(자세히)
자동화 컨트롤러 : 소스 인터페이스에 대한 정보를 얻는다. 1) 자동화 개체에게 IProviedClassInfo2 인터페이스 요청 2) IProviedClassInfo2::GetClasInfo메서드 호출하여 소스 인터페이스 정보를 얻는다. 얻은 정보를 사용하여 싱크 인터페이스를 생성할 수 있게 된다. 위의 두 과정은 생략 가능, 자동화 개체가 ActiveX컨트롤인 경우에는 제공할 필요가 있다. (C++ 컴파일러의 도움으로 #import지시어를 통해 소스 인터페이스를 구하여 이 정보를 기반으로 싱크 인터페이스를 생성하기 때문)

8 S_I  자동화 개체로(자세히) 이것을 위해서는 자동화 개체가 IConnectionPointContai-ner와 IConnectionPoint 인터페이스를 지원해야 한다. 1) 자동화 컨트롤러 : 자동화 개체에게 IConnectionPoint-Container 인터페이스 요청 2) IConnectionPointContainer::FindConnectionPoint 메서드 호출 : 소스 인터페이스에 대한 IConnectionPoint 인터페이스 포인터를 구한다. 3) IConnectionPoint::Advise 메서드 호출 : 앞에서 생성한 싱크 인터페이스 포인터를 매개변수로 넘겨준다. 이때 개체와 컨트롤러는 커넥션 포인터로 서로 연결된다.

9 S_I  자동화 개체로(자세히) IConnectionPointContainer
컨트롤러 IConnectionPointContainer 자동화 서버 (1)IConnectionPointContainer요청 (2)FindConnectionPoint 호출 (3)FindConnectionPoint 리턴 IConnectionPoint (4)Advise 호출 Idsipatch(싱크 인터페이스) (5)Idispatch 리턴 (6)IConnetionPoint::Unadvise : 커넥션 포인트 단절

10 Event 란 무엇인가? Automation Server Controller Connection Point mechanism
Source Object = event를 발생시키는 개체 Sink Object = event를 받아들이는 개체

11 Automation Component 에 Event 추가 - 실습

12 Event 구현 과정 개요 Evnet Interface 를 정의한다 Connection Point 클래스를 생성한다
ATL 자동화 개체 클래스가 생성된 Connection Point 클래스에서 파생되도록 지정한다 ATL 자동화 개체 클래스의 Connection Point Map 에 Connection Point 를 추가한다. Connection Point 클래스에 정의된 메서드를 호출한다.

13 Event Source 인터페스 정의 AddBack 프로젝트를 연다.
AddBack.idl 파일에 IAddBackEvent 이벤트 소스 인터페이스 정의 interface IAddBack : Idispatch { // 중간 생략 }; [ object, uuid(D90xxxx - xxxx- xxxx- xxxxxxxxx), dual, helpstring(“IAddBackEvent Intrface”), pointer_default(unique) ] interface IAddBackEvent : IDispatch { [Tools]메뉴의 [Create GUID] 툴 사용

14 Method 구현 ChangedAddEnd , ChangedSum 메서드

15 dispinterface 추가 library 섹션 안에 _DIAddBackEvent 이벤트 소스 인터페이스 정의
library ADDBACKLib { importlib("stdole32.tlb"); importlib("stdole2.tlb"); [ uuid(A7F7D1F0-E1C9-11d3-B7A5-0020AFA3553E), nonextensible ] dispinterface _DIAddBackEvent properties: methods: [id(1)] void ChangedAddEnd([in] short newVal); [id(2)] void ChangedSum([in] short newVal); }; // 중간생략

16 dispinterface 추가 Visual Basic 은 이중 인터페이스로 구현되는 Event Source 인터페이스를 인식하지 못한다. 따라서, Automation Object를 Visual Basic 에서도 사용할 수 있게 하기 위해서는 디스패치 인터페이스로 구현되는 Event Source 인터페이스를 정의해야 한다. 디스패치 인터페이스로 구현되는 Event Source 인터페이스명은 ‘_’ 로 시작함 - 관습

17 coclass 수정 coclass 에 이벤트 소스 인터페이스 추가
_DIAddBackEvent 디스패치 인터페이스를 디폴트 소스 인터페이스로 library ADDBACKLib { // 중간 생략 [ uuid(xxxx-xxxx-xxxx-xxxxxxxxxx), helpstring(“AddBack Class”) ] coclass AddBack [default] interface IAddBack; [default, source] dispinterface _DIAddBackEvent; [source] interface IAddBackEvent; };

18 Connection Point 클래스 생성
[Implement Connection Point] 대화상자 이용

19 생성된 Connection Point 클래스
AddBackCP.h Connection Point Class 는 ATL 의 IConnectionPointImpl 클래스에서 파생된다. IConnectionPointImpl 클래스 : Event Source 인터페이스에 대한 IConnectionPoint 인터페이스를 구현한 템플릿 클래스 Fire_ChangedAddEnd, Fire_ChangedSum : 각각 Event Source 인터페이스의 메서드(ChangedAddEnd, ChangedSum)와 대응됨

20 CProxy_DIAddBackEvent
디스패치 인터페이스로 정의된 Event Source 인터페이스에 대한 Connection Point 클래스 template <class T> class CProxy_DIAddBackEvent : public IConnectionPointImpl<T, &DIID__DIAddBackEvent, CComDynamicUnkArray> { //Warning this class may be recreated by the wizard. public: VOID Fire_ChangedAddEnd(SHORT newVal) } VOID Fire_ChangedSum(SHORT newVal) };

21 CProxyIAddBackEvent Custom 인터페이스로 정의된 Event Source 인터페이스에 대한 Connection Point 클래스 template <class T> class CProxyIAddBackEvent : public IConnectionPointImpl<T, &IID_IAddBackEvent, CComDynamicUnkArray> { //Warning this class may be recreated by the wizard. public: HRESULT Fire_ChangedAddEnd(SHORT newVal) } HRESULT Fire_ChangedSum(SHORT newVal) };

22 Event 발생시키기 Automation Server Controller
Connection Point 클래스에 정의된 Fire_ 메서드 호출 Automation Server Controller 주의: CProxyIAddBackEvent 와 CProxy_DIAddBackEvent 가 동일한 Fire_ 메서드를 가지고 있으므로 “::” 연산자를 이용하여 서로룰 구분해야 한다.

23 Fire 코드 추가 CAddBack::put_AddEnd
STDMETHODIMP CAddBack::put_AddEnd(short newVal) { // TODO: Add your implementation code here if(newVal <1) { // 중간 생략 return E_INVALIDARG; } if(m_AddEnd != newVal) { m_AddEnd = newVal; CProxyIAddBackEvent<CAddBack>::Fire_ChangedAddEnd(m_AddEnd); CProxy_DIAddBackEvent<CAddBack>::Fire_ChangedAddEnd(m_AddEnd); return S_OK;

24 Fire 코드 추가 CAddABack::Add 와 CAddBack::AddTen
STDMETHODIMP CAddBack::Add() { // TODO: Add your implementation code here m_Sum += m_AddEnd; CProxyIAddBackEvent<CAddBack>::Fire_ChangedSum(m_Sum); CProxy_DIAddBackEvent<CAddBack>::Fire_ChangedSum(m_Sum); return S_OK; } STDMETHODIMP CAddBack::AddTen() m_Sum += 10;

25 Fire 코드 추가 CAddBack::Clear STDMETHODIMP CAddBack::Clear() {
// TODO: Add your implementation code here m_Sum = 0; CProxyIAddBackEvent<CAddBack>::Fire_ChangedSum(m_Sum); CProxy_DIAddBackEvent<CAddBack>::Fire_ChangedSum(m_Sum); return S_OK; } 여기까지 입니다. 수고하셨습니다. Compile 하여 혹시 Error 는 없는지 확인하시기 바랍니다.

26 Automation Controller 에서 Event 받기 – 실습:Visual C++

27 개요 Visual C++ MFC Automation Controller 어플리케이션에서 Automation Object가 발생시킨 Event를 받아서 처리하기 위한 과정 ATL CComModule 개체 생성 Event Sink Object 클래스 구현 Event Sink Object 생성 사용 Event Sink Object 소멸 CComModule implements a COM server module

28 AddFront 프로젝트 수정 StdAfx.h StdAfx.cpp AddFront.cpp
#include <afxdisp.h> #import "..\AddBack\AddBack.tlb" no_namespace named_guids #include <atlbase.h> extern CComModule _Module; #include <atlcom.h> StdAfx.cpp AddFront.cpp #include "stdafx.h" #include <atlimpl.cpp> // The one and only CAddFrontApp object CAddFrontApp theApp; CComModule _Module;

29 AddFront 프로젝트 수정 CAddFront::InitInstance()
BOOL CAddFrontApp::InitInstance() { // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need. _Module.Init(NULL, NULL); AfxOleInit(); // 중간 생략 _Module.Term(); // Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump. return FALSE; }

30 EventHandler.h 작성 EventHandler.h 파일을 프로젝트에 추가합니다.
class ATL_NO_VTABLE CEventHandler : public CComObjectRoot, public IDispatchImpl<IAddBackEvent, &IID_IAddBackEvent, &LIBID_ADDBACKLib> { public: BEGIN_COM_MAP(CEventHandler) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(IAddBackEvent) END_COM_MAP() STDMETHOD(raw_ChangedAddEnd) (short newVal); STDMETHOD(raw_ChangedSum) (short newVal); }; EventHandler.h 파일을 프로젝트에 추가합니다.

31 EventHandler.cpp 작성 CEventHandler::raw_ChangedAddEnd(short new Val)
#include "stdafx.h" #include "resource.h" #include "EventHandler.h" STDMETHODIMP CEventHandler::raw_ChangedAddEnd (short newVal) { CString szMsg("AddEnd 속성이 변경되었습니다.\n"); CString szTemp; szTemp.Format("AddEnd 속성 값 : %d", newVal); szMsg += szTemp; AfxMessageBox(szMsg); return S_OK; }

32 EventHandler.cpp 작성 CEventHandler::raw_ChangedSum (short newVal)
STDMETHODIMP CEventHandler::raw_ChangedSum (short newVal) { CString szMsg("Sum 속성이 변경되었습니다.\n"); CString szTemp; szTemp.Format("Sum 속성 값 : %d", newVal); szMsg += szTemp; AfxMessageBox(szMsg); return S_OK; } EventHandler.cpp 파일을 프로젝트에 추가 합니다.

33 Sink Object 생성 AddFrontDlg.cpp 파일에 EventHandler.h 를 포함시킴
#include “AddFrontDlg.h” #include “EventHandler.h” CAddFrontDlg 클래스에 다음의 데이터 멤버 추가 protected: DWORD m_Cookie;

34 Sink Object 생성 CAddFrontDlg::OnCreate void CAddFrontDlg::OnCreate() {
// 중간 생략 HRESULT hr; IUnknown* pUnk; CComObject<CEventHandler>* pHandler; CComObject<CEventHandler>::CreateInstance(&pHandler); if(m_pDisp) pUnk = m_pDisp; else pUnk = m_pAddBack; hr = AtlAdvise(pUnk, pHandler->GetUnknown(), IID_IAddBackEvent, &m_Cookie); if(FAILED(hr)) AfxMessageBox("이벤트를 받을 수 없습니다."); UpdateData(FALSE); }

35 Sink Object 소멸 CAddFrontDlg::OnRelease void CAddFrontDlg::OnRelease()
{ // TODO: Add your control notification handler code here IUnknown* pUnk; if(m_pDisp) pUnk = m_pDisp; else AtlUnadvise(pUnk, IID_IAddBackEvent, m_Cookie); m_pDisp = 0; m_pAddBack = 0; }

36 Controller 테스트(Event)
이벤트를 제대로 받는지의 여부를 확인합니다.


Download ppt "제 7장 이벤트."

Similar presentations


Ads by Google