OLE 기술 주제 - 제4 강: COM 의 연결 점 이벤트 (상)

7400 단어 2.COMSTLShellHK
양 선생님
1. 앞에서 말 했 듯 이 COM 구성 요소 가 실 행 될 때 창 이 생 깁 니 다. 사용자 가 이 창 을 두 번 눌 렀 을 때 호출 자 에 게 알려 야 합 니 다.내 COM 구성 요 소 는 네트워크 에 있 는 파일 을 스 레 드 방식 으로 다운로드 합 니 다. 작업 이 완료 되면 호출 자 에 게 알려 야 합 니 다.나의 COM 구성 요 소 는 시계 기능 을 완성 합 니 다. 예약 시간 이 도 착 했 을 때 호출 자 에 게 알려 야 합 니 다........................................................................................2. 통지 하 는 방법 은 절차 갑 내부 에 어떤 사건 이 발생 했 을 때 을 에 게 통지 해 야 하 며 몇 가지 방법 을 사용 해 야 한다.
알림 모드
간단히 설명 하 다
코 멘 트
직접 소식
PostMessage()PostThreadMessage()
창 이나 스 레 드 에 메 시 지 를 보 냅 니 다.
네가 언제 집행 하 든 나 는 상관 하지 않 겠 다.
SendMessage()
메시지 응답 함수 바로 실행
메시지 처리 함수 가 실행 되 지 않 으 면 되 돌아 오지 않 습 니 다.
SendMessage(WM_COPYDATA...)
메 시 지 를 보 내 는 동시에 사용자 정의 데이터 도 가 져 갈 수 있다.
비교적 자주 사용 하기 때문에 단독으로 열거 하 였 다.
간접 소식
InvalidateRect()SetTimer()......
호출 된 함수 가 관련 메 시 지 를 보 냅 니 다.
이런 함수 가 너무 많아 요.
리 턴 함수
GetOpenFileName()......
사용자 가 파일 선택 을 바 꿀 때 리 셋 함 수 를 실행 합 니 다.
어이!얘 들 아, 내 전화 야. 일이 있 으 면 말 해.
COM 의 시대 에 상기 방법 들 은 기본적으로 돌 릴 수 없습니다. 왜냐하면................................................................................당연히 안 되 지!(그 나 저 나 ActiveX 처럼 로 컬 에서 만 실행 되 는 구성 요소 에 대해 서 는 당연히 창 메 시 지 를 보 낼 수 있 습 니 다.) 리 셋 함수 방식 은 COM 알림 방법 을 설계 하 는 기초 입 니 다.리 턴 함 수 는 본질 적 으로 특정한 함수 의 지침 을 나 에 게 알려 주 었 다. 내 가 필요 할 때 이 함 수 를 직접 불 렀 는데 이 리 턴 함수 가 무엇 을 했 는 지, 어떻게 했 는 지 나 는 전혀 관심 이 없다.자, 질문 하나 할 게 요. COM 인터페이스 가 뭐 예요?인 터 페 이 스 는 사실 관련 함수 의 집합 이다.따라서 COM 에 서 는 '리 셋 함수' 대신 '리 셋 인터페이스' (좀 더 분명하게 말 하면 포 장 된 '리 셋 함수' 집합 을 많이 사용 하 는 것) 를 사용 하고 리 셋 인 터 페 이 스 를 사용 하 며 우 리 는 '수신 기 인터페이스' 라 고도 부른다.그림 1. 클 라 이언 트 가 수신 기 인터페이스 지침 을 COM 에 전달 합 니 다.이벤트 가 발생 했 을 때 COM 호출 수신 기 인터페이스 함수 가 완료 되 었 습 니 다. 이 예제 프로그램 이 완 료 된 기능 은 클 라 이언 트 시작 구성 요소 (Simple 11. IEvent 1.1) 와 인터페이스 포인터 IEvent 1 * 입 니 다.인터페이스 호출 방법 IEvent 1: Advise () 는 클 라 이언 트 내부 의 수신 기 (sink) 인터페이스 포인터 (ICall Back *) 를 구성 요소 서버 에 전달 합 니 다.IEvent 1::Add () 를 호출 하여 두 정수 의 합 을 계산 합 니 다.그러나 계산 결 과 는 이 함 수 를 통 해 되 돌아 오지 않 고 ICallBack::FireResult () 클 라 이언 트 에 게 되 돌려 주기;클 라 이언 트 가 더 이상 이 벤트 를 받 아들 일 필요 가 없 을 때 IEvent 1: Unadvise () 를 호출 하여 구성 요소 와 의 연락 을 끊 습 니 다.3. 구성 요소 실현 절차 1. 작업 공간 (WorkSpace) 2 를 구축 하고 작업 공간 에서 ATL 프로젝트 (Project) 를 구축한다.예제 프로그램 에서 프로젝트 이름 은 Simple 11 이 고 모든 기본 옵션 을 받 습 니 다.3. ClassView 에서 마우스 우 클릭 메뉴 명령 New Atl Object 를 실행 하고 ALT 클래스 를 추가 합 니 다.   3 - 1 、 왼쪽 분류 Category 는 오 브 젝 트 를 선택 하고 오른쪽 오 브 젝 트 는 SimpleObject 를 선택 합 니 다 (사실은 기본 항목 입 니 다)   3 - 2, 이름 Name 카드 에 구성 요소 이름 을 입력 하 십시오.예제 프로그램 에서 Event 1 (주 1)   3 - 3 、 속성 Attributes 카드 에서 인터페이스 유형 인 터 페 이 스 를 수정 하여 맞 춤 형 Custom (주 2) 4 、 ClassView 에서 인터페이스 (IEvent 1) 를 선택 하고 마우스 우 클릭 메뉴 에 함수 Add Method 를 추가 합 니 다. 그림 2 、 인터페이스 함수 Add ([in] long n1, [in] long n2) 그림 3 、 인터페이스 함수 Advise ([in] ICallBack * pCallBack, [out] long * pdwCookie) 그림 4 、인터페이스 함수 Unadvise ([in] long dwCookie) 를 추가 하면 알 수 있 습 니 다. Add () 함수 에는 [out], [retval] 같은 IDL 속성 이 없습니다. 헤헤, 우 리 는 원래 Add () 함 수 를 통 해 직접 계산 결 과 를 얻 으 려 고 하지 않 았 기 때 문 입 니 다.그렇지 않 으 면 리 셋 인 터 페 이 스 를 어떻게 보 여 줍 니까? -) 그리고 함수 Advise () 에서 정수 dwCookie 를 되 돌려 야 합 니 다. 이것 은 무엇 을 하 는 것 입 니까?이 치 는 매우 간단 합 니 다. 왜냐하면 우리 구성 요 소 는 여러 대상 의 리 셋 연결 을 동시에 지원 하고 싶 기 때 문 입 니 다.따라서 클 라 이언 트 가 우리 구성 요소 에 인 터 페 이 스 를 전달 할 때 나 는 유일한 쿠키 번호 로 신분 을 표시 하고 나중에 연결 을 끊 을 때 Unadvice () 는 이 쿠키 의 신분 번 호 를 다시 나 에 게 주어 야 한다. 그러면 나 는 누가 끊 으 려 고 하 는 지 알 수 있다.5. 리 셋 인터페이스 ICallBack 의 IDL 정 의 를 추가 합 니 다.IDL 파일 을 열 고 수 동 으로 입력 한 다음 저장 합 니 다.
4. 567913. 6. 리 턴 인터페이스 함수 증가
그림 5. 리 턴 인터페이스 함수 증가
사실 예전 의 방법 과 마찬가지 로 인 터 페 이 스 를 잘못 선택 하지 않도록 주의 하면 된다.
그림 6 、 인터페이스 함수 증가 FireResult([in] long nResult)
우 리 는 정수 와 결 과 를 계산 한 후에 이 반전 인터페이스 함수 로 클 라 이언 트 에 게 피드백 해 야 한다.
7. 구성 요소 내부 에 리 셋 인터페이스 포인 터 를 저장 하 는 배열 을 추가 합 니 다.
방금 말 했 듯 이 이 구성 요 소 는 여러 대상 의 리 셋 연결 을 지원 할 계획 이 므 로 하나의 배열 로 저장 해 야 합 니 다.ClassView 에서 CEvent 1 종 류 를 선택 하고 구성원 변 수 를 추가 합 니 다. Add Member Variable...
그림 7. ICallBack * 을 저장 하 는 배열 을 추가 합 니 다.
물론 하나의 배열 을 저장 하 는 데 는 여러 가지 방법 이 있 을 수 있다.예제 프로그램 은 비교적 간단 하여 10 개의 요소 공간의 구성원 배열 변 수 를 정의 했다.STL 사용 을 배 웠 다 면 vector 등 용기 로 도 가능 하 다.
주의!주의!주의!구조 함수 에서 배열 요 소 를 NULL 로 초기 화 하 는 것 을 잊 지 마 세 요.
8. 자, 이제 모든 코드 를 완성 합 니 다.
import "oaidl.idl";
import "ocidl.idl";
[
	object,
	uuid(7E659BB1-FB79-4188-9661-65CA22B6A3E6),	//    IID     GUDIGEN.EXE   
	
	helpstring("ICallBack Interface"),
	pointer_default(unique)
]
interface ICallBack : IUnknown
{

};

[
	object,		//          ,                     
	uuid(7E659BB0-FB79-4188-9661-65CA22B6A3E6),
	
	helpstring("IEvent1 Interface"),
	pointer_default(unique)
]
interface IEvent1 : IUnknown
{
	[helpstring("method Add")] HRESULT Add([in] long n1, [in] long n2);
	[helpstring("method Advise")] HRESULT Advise([in] ICallBack * pCallBack, [out] long * pdwCookie);
	[helpstring("method Unadvise")] HRESULT Unadvise([in] long dwCookie);
};

[
	uuid(695C9BB2-2AE9-4232-8225-17AB8BD3BABC),
	version(1.0),
	helpstring("Simple11 1.0 Type Library")
]
library SIMPLE11Lib
{
	importlib("stdole32.tlb");
	importlib("stdole2.tlb");

	[
		uuid(6FCF997C-C811-49DB-9D16-46FAF8D24822),
		helpstring("Event1 Class")
	]
	coclass Event1
	{
		[default] interface IEvent1;
		//       ,   VB     ,    [source,default]   
		[source, default] interface ICallBack;	
	};
};

4. 클 라 이언 트 실현 절차
모두 예제 프로그램 을 다운로드 한 후 클 라 이언 트 의 실현 프로그램 을 찾 아 보 세 요.여기 서 나 는 수신 기 가 어떻게 구성 되 었 는 지 에 대해 서 만 설명 한다.
그림 8. ICallBack 파생 수신 기 류 CSink
ICallBack 에서 클래스 CSink 를 파생 합 니 다.확인 후 IDE 에 서 는 ICallBack 의 헤더 파일 을 찾 을 수 없다 는 경고 가 있 습 니 다. 컴 파일 할 때 만\# import 가 xxxx. tlh, xxxx. tli 파일 을 만 들 수 있 기 때문에 이 파일 들 은 ICallBack 의 성명 이 있 습 니 다.
여기 ICallBack 은 COM 인터페이스 이기 때문에 CSink 는 사례 화 할 수 없습니다. 컴 파일 을 하면 덩어리 (주 3) 의 오 류 를 얻 을 수 있 습 니 다. virtual 함 수 를 실현 하지 못 했다 고 보고 합 니 다.그리고 우 리 는 오류 보고 에 따라 모든 가상 함 수 를 실현 할 수 있 습 니 다.
STDMETHODIMP CEvent1::Add(long n1, long n2)
{
	long nResult = n1 + n2;
	for( int i=0; i<10; i++)
	{
		if( m_pCallBack[i] )  //         
			m_pCallBack[i]->Fire_Result( nResult );	//      /  
	}

	return S_OK;
}

STDMETHODIMP CEvent1::Advise(ICallBack *pCallBack, long *pdwCookie)
{
	if( NULL == pCallBack )	//          ?!
		return E_INVALIDARG;

	for( int i=0; i<10; i++)	//               
	{
		if( NULL == m_pCallBack[i] )	//    
		{
			m_pCallBack[i] = pCallBack;	//       
			m_pCallBack[i]->AddRef();	//       +1

			*pdwCookie = i + 1;	// cookie       
  		// +1         0,  0    

			return S_OK;
		}
	}
	return E_OUTOFMEMORY;	//   10   ,      
}

STDMETHODIMP CEvent1::Unadvise(long dwCookie)
{
	if( dwCookie<1 || dwCookie>10 )	//       ?    
		return E_INVALIDARG;

	if( NULL == m_pCallBack[ dwCookie - 1 ] )	//     ,           
		return E_INVALIDARG;

	m_pCallBack[ dwCookie -1 ]->Release();	//       -1
	m_pCallBack[ dwCookie -1 ] = NULL;		//           

	return S_OK;
}

다섯.
, 소결 COM 구성 요소 가 이 벤트 를 실현 하고 이러한 기능 을 알 리 는 데 두 가지 기본 적 인 방법 이 있 습 니 다.오늘 소개 한 리 턴 인터페이스 방식 은 매우 좋 고 속도 가 빠 르 며 구조 가 뚜렷 하 며 실현 도 복잡 하지 않다.다음 회 서 는 연결 점 방식 (Support Connection Points) 을 소개 하 는데 연결 점 방법 이 사실 그다지 좋 지 않 고 속도 가 느 리 며 (원 격 DCOM 방식 이 라면 신중하게 선택해 야 한다) 구조 가 복잡 하고 유일한 장점 은 ATL 이 이 를 포장 한 것 이기 때문에 실현 하기 가 오히려 간단 하 다.소개 하지 않 으 면 안 됩 니 다. 마이크로소프트 의 절대 다수 지원 이벤트 의 구성 요 소 는 모두 연결 점 으로 이 루어 지기 때 문 입 니 다. 크..................................................

좋은 웹페이지 즐겨찾기