성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] Working with Rust Libraries from C#...
[정성태] Detecting blocking calls using asyn...
[정성태] 아쉽게도, 커뮤니티는 아니고 개인 블로그입니다. ^^
[정성태] 질문이 잘 이해가 안 됩니다. 우선, 해당 소스코드에서 ILis...
[양승조
] var대신 dinamic으로 선언해서 해결은 했습니다. 맞는 해...
[양승조
] 또 막혔습니다. ㅠㅠ var list = props[i].Ge...
[양승조
] 아. 감사합니다. 어제는 안됐던것 같은데....정신을 차려야겠네...
[정성태] "props[i].GetValue(props[i])" 코드에서 ...
[정성태] 저렇게 조각 코드 말고, 실제로 재현이 되는 예제 프로젝트를 압...
[정성태] Modules 창(Ctrl+Shift+U)을 띄워서, 해당 Op...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <br /> <div class='mainCenterTitle'>COM 개체의 이벤트를 구독하는 코드 제작</div><br /> <br /> 지난번에는, C++ COM 개체에서 이벤트를 발생시키는 2가지 유형에 대해서 알아봤습니다.<br /> <br /> <pre class='code'> VC++ : 10. COM 이벤트에서 반환값을 가진 콜백 정의 ; <a target='_tab' href='/2/0/588'>http://www.sysnet.pe.kr/2/0/588</a> </pre> <br /> 먼저, 반환값을 C++ COM 개체에서 Invoke의 6번째 인자인 <b>/* [out] */ VARIANT *pVarResult</b>에서 처리하는 경우, 해당 ActiveX COM 개체를 WinForm 화면에 그려넣고 이벤트 코드를 생성하게 되면 다음과 같은 C# 코드가 나옵니다.<br /> <br /> <pre class='code'> <b>void</b> axTestObjectControl1_OnMethodCalled(object sender, AxAtlComSampleLib. _ITestObjectControlEvents_OnMethodCalledEvent e) { } </pre> <br /> 물론, 동작은 잘 됩니다. 반면에, 반환값을 인자로 넣어서 처리하는 이벤트 콜백에 대해서는 다음과 같은 식으로 코드가 처리되고,<br /> <br /> <pre class='code'> <b>int</b> axTestObjectControl1_OnMethodCalled(object sender, AxAtlComSampleLib. _ITestObjectControlEvents_OnMethodCalledEvent e) { <b>return 1000;</b> } </pre> <br /> 아쉽게도 위의 콜백 함수는 정상적으로 호출되지 않습니다. 부가적으로, 이에 대한 _ITestObjectControlEvents 인터페이스가 어떻게 interop 되고 있는지 Object Browser를 통해서 살펴보면 다음과 같이 정의되어 있는 것을 확인할 수 있습니다. (당연한 결과죠!)<br /> <br /> <pre class='code'> int OnMethodCalled(int cookie) Member of AtlComSampleLib._ITestObjectControlEvents </pre> <br /> <hr style='width: 50%' /><br /> <br /> 문제는 여기부터입니다. 해당 3rd-party에서 제공되는 COM 개체가 반환값 처리를 인자로 넣어서 처리하는 방식으로 해버렸고, 그러한 컨트롤을 WinForm에 그려 넣고 이벤트를 구독하니 이벤트 콜백을 받을 수가 없게 된 것입니다.<br /> <br /> 물론, 이벤트 처리 방식을 바꿔 달라고 3rd-party 업체에 요구할 수도 있지만 그것이 항상 ^^ 말처럼 쉽지는 않은 것도 현실입니다.<br /> <br /> 자!... 그럼 이제 어떻게 해야 할까요?<br /> <br /> 이런 경우, 해당 메서드가 정의된 인터페이스를 C# 측에서 다시 정의하면 됩니다. 예를 들어, "_ITestObjectControlEvents" 이벤트를 C#에서 다음과 같이 재정의하는 것입니다.<br /> <br /> <pre class='code'> [TypeLibType(4096)] [ComVisible(true)] [Guid("<b>AED7C2E7-C9C2-4D1B-A760-BE1A79C06EC2")] // 1. Guid 값이 일치해야 하고. [InterfaceType(2)]</b> public interface _IMyTestObjectControlEvents // 인터페이스 이름은 자유롭게 정의 { [<b>DispId(1)</b>] // 2. Dispid 값이 일치해야 하고. <b>void OnMethodCalled(int cookie, out int result);</b> // 3. 보정된 메서드 정의 } </pre> <br /> C# 코드로 재정의했다고 해서 안될 것은 없습니다. 중요한 것은 Guid 값이기 때문에 그것만 일치하면 이벤트에 대해 정상적으로 구독하는 것이 가능합니다.<br /> <br /> 그럼... 이제 어떻게 해당 ActiveX 개체에 대해 위에서 새롭게 정의한 이벤트를 구독하도록 하느냐는 것인데... 이를 위해서는 약간의 COM 지식이 선행되어야 다음과 같은 코드가 작성될 수 있습니다. (제가, 여전히 .NET을 하면서도 C/C++ 프로그래머를 좋아하는 이유입니다. ^^ 일반적인 닷넷 프로그래머라면 아래와 같은 해법을 낼 수 없기 때문입니다.)<br /> <br /> <pre class='code'> private void Form1_Load(object sender, EventArgs e) { object obj = <b>axTestObjectControl1.GetOcx();</b> IConnectionPointContainer connectionPoint = obj as IConnectionPointContainer; IConnectionPoint point; Guid guid = new Guid("{<b>AED7C2E7-C9C2-4D1B-A760-BE1A79C06EC2</b>}"); connectionPoint.FindConnectionPoint(ref guid, out point); int dwCookie; point.<b>Advise(this, out dwCookie);</b> } </pre> <br /> 위의 코드는 해당 COM 개체가 구현하는 이벤트 인터페이스를 찾아내고, 그에 대해 "구독"을 하겠다고 지정하는 것입니다. 보시는 것처럼, ConnectionPoint에 대해 _IMyTestObjectControlEvents의 특성으로 지정된 Guid 값을 사용하고 마지막에 this를 인자로 Advise 메서드를 호출해서 구독하게 되는 것입니다.<br /> <br /> 여기서 끝이 아니고, this에 해당하는 클래스가 다음과 같이 "_IMyTestObjectControlEvents" 이벤트를 상속받아서 구현해줘야 합니다. (물론, this를 전달하지 않고 별도로 _IMyTestObjectControlEvents 인터페이스를 구현한 타입의 인스턴스를 사용해도 무방합니다.)<br /> <br /> <pre class='code'> public partial class Form1 : Form, <b>_IMyTestObjectControlEvents</b> { ; [...생략...] #region _IMyTestObjectControlEvents Members <b>public void OnMethodCalled(int cookie, out int result)</b> { result = 5000; } #endregion ; [...생략...] } </pre> <br /> 이제, 실행시켜 보면 정상적으로 이벤트를 구독하는 것을 확인할 수 있습니다. 문제 해결 끝!<br /> <br /><br /><hr /><span style='color: Maroon'>[이 토픽에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
6398
(왼쪽의 숫자를 입력해야 합니다.)