ActiveX

액티브X 생성에서 배포까지

디버그정 2008. 9. 6. 16:35

액티브X 생성에서 배포까지

 

범수 NDS e- 사업팀

 

필자가 액티비X 컨트롤을 처음 접한 것은 지난 96년 여름이었다.

당시 자바 애플릿으로 프로젝트를 진행하던 중 애플릿의 기능적 한계로 인해 새로 나온

액티브X 마이크로소프트의 기술을 사용하는 모험을 하게 됐다. 이때 액티브x는 상당히 새로운

(OLE를 아는 사람들은 별 것 아니라고 말했지만) 기술이어서 많은 사람들이 분주히 ms의 각종
컨퍼런스를 
참석하러 다녔던 기억이 안다. 그렇게 시작된 액티브x 컨트롤 개발이 벌써 6년째 접어들었다. 현재의 상황과 비교해 보면 과거에는 액티브x 컨트롤을 개발하기 위한 툴도, 문서도 부족했지만
지금은 아주 많다.

또한 당시 국내외에 인터넷 익스플로러보다는 넷스케이프 네비게이터의 위력이 더 컸기 때문에
브라우저 호환성의
문제를 안고 있는 액티브x 기술은 개발자들을 고민에 빠뜨렸다.

 

그러나 현재는 넷스케이프와 인터넷익스플로러의 입지가 바뀌었으며 액티브x는 더욱 광범위하게
사용되고 있다. 인터넷
기반의 프로젝트에 좀더 막강한 기능을 제공하기 위해서 DHTML, 자바 스크립트,
플릿, 플래시 등 다양한 기술을 활용할 수 있지만
이중에서도 가장 막강한 것이
액티브x 컨트롤이라 할 수 있다. 액티브x 컨트롤을 사용함으로써 윈도우 플랫폼의 대부분의 기능을

자유롭게 사용할 수 있다. 지금부터 이러한 액티브x 컨트롤 만드는 방법을 알아보고 그 과정에서 부딪히는 수많은 문제를 하나씩 해결해 보자

 

개발 도구의 선정

컨트롤을 개발할 때 제일 먼저 고민하는 것이 개발도구일 것이다. 지금은 대부분의 개발도구가
컨트롤 개발을 지원하므로
더욱 그러리라 생각된다. 현재 사용할 수 있는 개발도구는 매우 많다.

 

개발도구 : 비주얼 C++(ATL), MFC, 비주얼 베이직, 델파이 외 다수

 

필자는 이 중에서 늘 비주얼 C++를 사용한다. 가장 지원이 잘 되는 개발도구이기 때문이다.
그렇지만 개발도구는 개발자가
잘 쓸 수 있는 것이 더 좋다고 생각된다. 하지만 필자의 또 다른 고민은
ATL을 사용할 것인가 MFC를 사용할 것인가를 판단하는 것이다.

이 두가지 선택에는 표1에서와 같이 장단점이 있다.

사용자 삽입 이미지

 

즉 크기인가 개발의 용이성인가의 문제다. 필자의 경우는 개발할 컨트롤의 특성에 따라 다르게 사용한다. 즉 모듈이 작고 UI간단한 경우 ATL을 사용하고 비교적 화면처리가 많은 경우 MFC를 사용한다. 프로젝트에서 컨트롤을 개발할 경우 어떤 사람은 모든 컨트롤을 ATL로 만들어야 한다고 말한다. 물론 괜찮은 방법일 수도 있지만, 한가지 생각할 것은 프로젝트를 만든 사람이 끝까지 책임지지 않는다는 것이다. 모든 컨트롤을 ATL로 만드는 데는 고급인력을 필요로 하기 때문에 만약 후임 개발자에게 인수인계해야 할 경우 상황을 더욱 어렵게 만들 수 있다. ATL 개발자가 많지 않은 국내 현실에서는 더욱 그러하다.

 

이번 연재에서는 MFC를 사용해, 좀더 다양한 기능을 제공하는 컨트롤 제작시 발생하는 문제점을 알아보겠다.

 

 

컨트롤의 개발

이제 개발도구가 정해졌으니 컨트롤을 개발해 보자. 가장 먼저 할 일은 무엇을 개발할지 스펙을 정하고 비주얼 C++ 프로젝트를 생성하는 것이다. 필자는 현재 IE5.5 환경에 비주얼 C++ 6.0 서비스팩 4를 사용하고 있다. 앞으로의 설명은 이를 기준으로 진행하겠다. 우선 비주얼 C++을 실행해 File / New를 선택한다.

 

화면1에서처럼 Start라는 프로젝트를 생성한다. 그리고 이를 Release 모드로 컴파일하면 하나의 Start.ocx라는 컨트롤을 얻을 수 있다.

사용자 삽입 이미지


이때 결정해야 할 것은 사용하는 MFC.dll Share로 사용할 것인지 아니면 액티브X 컨트롤 내로 포함시키는 Static으로 사용할 것인지이다.

 

Project/Setting 메뉴를 누르면 화면2를 볼 수 있는데 여기서 이를 설정할 수 있다 이 옵션 선택에서 각각에 대한 장단점을 살펴보면 2와 같다.

사용자 삽입 이미지

이러한 장단점이 있으므로 자신의 프로젝트에 맞게 선택해야 한다. 필자의 경우 컨트롤을 많이 사용하는 인터넷 기반 패키지를 개발할 때는 Share로 사용한다. 대신 패키지 설치시 MFC.dll을 미리 배포하는 방식으로 한다. 그러나 일반 인터넷 사이트인 경우에는 Static을 사용한다.

사용자가 이 사이트를 방문했는데 MFC dll이 설치되고 리부팅하라는 메시지가 나오면(윈도우 2000 이전버전일 경우) 당황할 것이기 때문이다.

 

Static으로 사용하는 경우 MFC만 약 236kb 정도를 차지하므로 컨트롤의 코드 부분에서 코드가 너무 커지지 않도록 주의해야 한다. 이것을 실제로 배포할 때는 cab파일로 압축해 배포하는데 대개 크기가 반 이상 줄어들게 된다. 이렇게 압축했을 때 크기가 250kb를 넘지 않으면 배포가 가능하다. 필자는 압축해서 450kb정도의 컨트롤을 배포한 적이 잇는데 고객으로부터 큰 불평은 듣지 않았다.

 

 

브라우저에 올리기

이제  만들어진 액티브x 컨트롤을 인터넷 익스플로러에 올려보자. 일단 IE에 올리려면 우리는 우리가 만든 컨트롤의 클래스ID를 알아야 한다. ID GUID, 즉 세상에서 유일한 아이디로 만들어지므로 우리가 만든 컨트롤은 어느 누가 만든 컨트롤과도 구분할 수 있다따라서 여러분이 각자 만들게 되면 컨트롤 이름은 모두 Start.ocx이지만 클래스 아이디는 모두 다른 것이 생성된다. 결국 이름만 같고 다른 컨트롤이 되는 것이다.

 

이 클래스 ID는 프로젝트 안의 Start.ocx(프로젝트명.odl)이라는 파일에서 발견할 수 있다. 이 파일안에는 여러개의 GUID가 있는 데 그중 가장 아래부분을 보면 다음과 같다.

 

// Class information for CStartCtrl

[ uuid(63C4E7C7-5286-4003-95CF-CB29DE0173D3),

  helpstring("Start Control"), control ]

coclass Start

{

  [default] dispinterface _DStart;

  [default, source] dispinterface _DStartEvents;

};

 

이 부분이 컨트롤의 클래스 ID를 담는 부분이다. 63C4E7C7-5286-4003-95CF-CB29DE0173D3 이 필자가 만든 Strat 컨트롤의 클래스 ID이고, 여러분은 이 부분에 다른 값이 들어 있을 것이다.

한번 찾아보기 바란다. 이 클래스 ID를 갖고 간단한 HTML 문서(Start.html)을 만들어 보자.

 

<html>

<body>

<OBJECT ID = "Start" WIDTH = 300 HEIGHT = 200

   classid = "clsid:63C4E7C7-5286-4003-95CF-CB29DE0173D3">

</OBJECT>

</body>

</html>

 

그리고 Start.html을 브라우저로 열었을 때 화면3이 나타난다면 일단 성공한 것이다. 필자는

이 화면을 너무 많이 봐서 질릴 정도지만 아직 가야할 길이 머니 좀더 분발하기 바란다.

사용자 삽입 이미지

 

Cab 파일로 압축하기

앞서 만든 Start.html은 먼저 컨트롤이 시스템에 설치된 경우에만 잘 나타날 것이다.
이 컨트롤을 웹에서도
보게 하려면 좀 더 많은 작업을 거쳐야 한다. 가장 먼저 압축을 한다. 압축형식은 MS에서 제공하는 Cab 파일이면 압축 프로그램은 cabarc.exe가 있다. 이것은 http://msdn.microsoft.com/workshop/management/cab/cabdl.asp 에서

다운받을 수 있다. Cab으로 압축하기 전 Inf파일을 준비해야 하는 데 ocx와 필요한 dll들을 어떻게 시스템에 설치해야 하는지를 브라우저에게 알려주는 정보(Informaion) 파일이다.

 

간단한 Start.inf 파일을 만들어 보자. 앞서 설명한 mfc dll을 어떻게 사용했느냐에 따라 두가지로 구분해 작성할 수 있을 것이다.

 

1) MFC dll Static으로 사용한 경우

; File name - Start.inf

; INF file for Start.ocx

 

[version]

signature = "$CHICAGO$"

AdvancedINF = 2.0

 

[Add.Code]

Start.ocx = Start.ocx

 

[Start.ocx]

file-win32-x86 = thiscab

FileVersion = 1.0.0.1

clsid = {63C4E7C7-5286-4003-95CF-CB29DE0173D3}

RegistedServer = yes

 

2) MFC dll Share로 사용한 경우

[version]

signature="$CHICAGO$"

AdvancedINF=2.0

[Add.Code]

Start.ocx=Start.ocx

msvcrt.dll=mfc42.dll

olepro32.dll=olepro32.dll

[start.ocx]

file-win32-x86=thiscab

clsid={63C4E7C7-5286-4003-95CF-CB29DE0173D3}

FileVersion=1.0.0.1

RegisterServer=yes

[msvcrt.dll]

FileVersion=4.20.0.6164

hook=mfc42installer

[mfc42.dll]

FileVersion=4.2.0.6256

hook=mfc42installer

[olepro32.dll]

FileVersion=4.2.0.6256

hook=mfc42installer

[mfc42installer]

file-win32-x86=

http://activex.microsoft.com/controls/vc/mfc42.cab

run=%EXTRACT_DIR%\mf42.exe

 

1번의 경우 배포해야 할 것이 Start.ocx 하나이므로 비교적 간단하다.

그러나 2번의 경우 기본적으로 컨트롤이 사용하는 dll msvcrt.dll, mfc42.dll, olepro32.dll인데

이들 dll을 어떻게 설치할지 잘 정의한다. 물론 컨트롤에 따라 자체적으로 dll을 사용하는 경우

이들 dll을 같은 cab 파일안에 넣고 어떻게 설치할지 inf파일에 잘 정의해줘야 한다.

 

여기서는 세 개의 dll mfc42installer 항목에서 설치하도록 정의하는데 mfc42installer 항목을 보면

mfc42.cab MS에서 다운받고 이 Cab파일을 푼 폴더에서 설치 프로그램(mfc42.exe)을 실행하도록 정의하고 있다.

 

이 설치프로그램이 가동된 경우 일부 시스템(2000 이전)은 설치한 후 재가동을 요구하기도 한다. 이러한 재가동률을 최소화하려면 사용하는 비주얼 C++의 버전에 맞는 각 dll의 파일버전 값을 정확히 기술해야 한다. 각 비주얼 C++의 버전별 dll의 버전은 http://supprot.microsoft.com/support/kb/articles/Q167/1/58.ASP 에 잘 기술되어 있다.

 

이제 Start.inf Start.ocx가 준비됐으므로 이것으로 Start.cab를 만들면 된다. 명령은 다음과 같다.

 

cabarc -s 6144 N Start.cab Start.ocx Start.inf <enter>

여기서 N Create를 말하는 옵이다.(new를 의미하는 듯) 그리고 -s 6144 cab 파일에 인증키를 넣기 위해 6144바이트를 비워두라는 옵션이다. cab 파일을 만들었으므로 앞서 만든 Start.html을 수정해보자.

이때 CODEBASE 속성에 cab 파일명을 적고 이 파일에 들어있는 ocx의 버전을 적어주는 데 Start 프로젝트 리소스의 버전에서 파일과 제품의 버전을 적으면 된다. 이때 주의할 것은 버전의 세부항목이 콤마로 구분되어 있다는 것이다.

 

<html>

<body>

<OBJECT ID = "Start" WIDTH = 300 HEIGHT = 200

  classid = "clsid:63C4E7C7-5286-4003-95CF-CB29DE0173D3"

  CODEBASE = "Start.cab#Version=1,0,0,1">

</OBJECT>

</body>

</html>


이제 Start.html Start.cab을 웹서버의 같은 폴더에 올려놓고 IE로 열어보자. 그러면 화면4와 같은 에러메시지를 접하게 될 것이다.

사용자 삽입 이미지

무엇인 문제인가. 문제는 여러분이 작성한 컨트롤(Start.ocx)이 인증돼 있지 않다는 점이다.

 

코드사인하기

컨트롤을 작성하면 만든 이는 사용자가 이 컨트롤을 다운받을 때 얼마나 안전한지에 대한 보증을 해야 한다. 사용자가 뭘 믿고 모르는 사람이 만든 컨트롤을 자신의 PC에 설치하겠는가.

 

컨트롤의 인증은 공개키 기반의 인증키로 하게 되는데, 이때 인증기관의 신뢰도가 가장 중요하다. 그래서 대부분 미국 베리사인과 같은 신뢰성 있는 인증기관으로부터 인증서를 받아 자신의 컨트롤을 인증하고 있다. 즉 그렇게 인증을 하면 사용자는 컨트롤이 자신의 pc설치될 때 다음과 같은 메시지 "XX 개발사가 만들고 베리사인이 보증한 컨트롤입니다."를 접하게 된다. 그럼 사용자는 좀더 안심하고 컨트롤을

설치하게 되는 것이다.

 

베리사인에 인증키를 신청해 키를 받게 되면 MS로부터 인증용 툴
http://digitalid.verigign.com/developer/ms_pick.html
을 다운받아야 한다.

이 툴을 특정 폴더에 풀고 그 폴더에 cabarc.exe, Start.ocx, Start.inf를 넣자. 우리가 인증해야 할 대상은 두 개의 파일인데, 하나는 ocx이고 다른 하나는 중간에 생성되는 cab파일이다. 인증 절차는 다음과 같으며 IE.5.X가 설치된 컴퓨터에서의 인증방법이다.

 

필자는 이러한 과정의 많은 타이핑을 줄이기 위해 배치파일(Start.bat)을 만들어 사용한다.


SignCode -spc myKey.spc -v myKey.pvk -n Start -i

http://www.myurl.com

-$ commercial -t http://timestamp.verisign.com/scripts/timestamp.dll

Start.ocx <enter>

chktrust -q Start.ocx <enter>

cabarc -s 6144 N Start.cab Start.ocx Start.inf <enter>

SignCode -spc myKey.spc -v myKey.pvk -n Start -i

http://www.myurl.com

-$ commercial -t http://timestamp.verisign.com/scripts/timestamp.dll

Start.cab <enter>

chktrust -q Start.cab <enter>

 

 

보안상의 경고메시지를 피하기 위해 우리는 한 가지를 더 해줘야 한다. 그것은 초기화와 스크립트에 대한 안전표시(Safe for Scripting/Initialization)로 이 컨트롤을 스크립트 엔진에서 사용해도 안전하다는 표시다.

 

참고) 인증서 신청과 필자의 실수담

베리사인으로부터 인증서를 받는 절차를 알아보자. 국내 업체가 베리사인으로부터 인증서를 받으려면 먼전 DUNS 넘버를 받는 것이 좋다. 이 번호는 각각의 회사에 대한 국제적 공증번호이다. 베리사인이 특정회사를 위해 인증키를 배포할 때 그 회사가 실제로 존재하고 또 어떤 회사인지 파악해야 보증을 할 수 있는데, 이때 DUNS넘버는 그 과정을 대신하게 된다. 만약 DUNS 넘버가 없다면 여러분은 자신의 회사를 소개하는 영문자료를 베리사인에 제출해야 한다. DUNS 넘버는 D&B 한국지사에서 발행하고 있으면 무료와 유료( 5만원)가 있다. 유료인 경우 DUNS 넘버에 대한 공식문서를 받을 수 있으므로 나중에 베리사인으로부터 인증서를 좀더 빨리 받으려고 할 때 이 공식문서를 사용할 수 있어 유리하다. DUNS 넘버를 만드려면 4일에서 늦으면 일주일 정도 소요된다. 그러나 DUNS 넘버를 베리사인이 확인하는 데까지 한달이라는 시간이 더 걸린다. 이때 좀더 빨리 진행하기 위해서는 DUNS 넘버에 대한 공식문서를 베리사인에게 팩스로 보내준다. DUNS 넘버를 받고 베리사인에게 IE용 인증키를 신청하면 몇 가지 절차를 거친 뒤 일주일에서 보통 보름정도 뒤에 개인키(myKey.pvk)와 공개키(myKey.spc) 한 쌍을 받게 된다.

필자는 가끔 프로젝트를 하면서 고객 회사의 인증키를 대신 신청해주곤 하는데 한번은 베리사인의 신청서를 작성하다가 첫부분에 Developer ID를 쓰라고 해서 필자가 개발자라는 생각에 고객의 회사가 아닌 필자의 회사를 적었다. 나중에 인증키를 받고 보니, Common Name(인증키의 ID)이 고객회사로 돼야 하는데 그만 본인 회사로 돼 있는것이 아닌가. 그래서 취소하고 재발급받느라 고생한 적이 있다. 이처럼 인증서를 대리신청할 경우에는 주의를 기울여야 한다.

 

 

초기화와 스크립트에 대한 안전표시

앞서 여러분이 했던 코드사인은 다운로드를 안전하게 수행하기 위한 절차였다.

MFC는 기본적으로 위자드에 의해 생성된 컨트롤에 스크립팅과 컨트롤 초기화를 위한 안전처리가 돼 있다. 따라서 IE에서 보안이 보통 이상인 경우 컨트롤이 안전하지 않다는 메시지가 출력된다. 이것을 해결하는 방법은 두 가지로, 하나는 IObjectSafety 인터페이스를 구현하는 것이고 다른 하나는 컨트롤의 DllRegisterServer 함수안에 레지스트리에 안전표시를 하도록 하는 것이다. 여기서는 두 번째 방법을 사용하겠다.

 

MS는 이를 위해 두개의 함수를 별도로 제공하고 잇다. 리스트1,2의 두 파일을 만들어 프로젝트에 추가하자. 그런 다음 우리 프로젝트의 Start.cpp #include "CatHelp.h"를 추가하고 두 개의 GUID를 추가한다.

const CATID CATID_SafeForScripting    =

{0x7dd9501, 0x9882, 0x11cf, {0x9f, 0xa9, 0x00, 0xaa, 0x00, ox6c, 0x42, 0xc4}};

const CATID CATID_SafeForInitializing    =

{0x7dd9501, 0x9882, 0x11cf, {0x9f, 0xa9, 0x00, 0xaa, 0x00, ox6c, 0x42, 0xc4}};

 

다음 우리 컨트롤의 클래스 ID를 다음과 같은 형식으로 정의하자. 이때 _ctlid 값은 CLSID와 같아야 한다.

const GUID CDECL BASED_CODE _ctrid =

{{0x63C4E7C7, 0x5286, 0x4003, {0x95, 0xcf, 0xcb, 0x29, 0xde, 0x01, 0x73, oxd3}}; // clsid: 63C4E7C7-5286-4003-95CF-CB29DE0173D3

 

 

마지막으로 Start.cpp DllRegisterServer 함수를 다음과 같이 수정하면 된다.

STDAPI DllRegisterServer()

{

 AFX_MANAGE_STATE(_afxModuleAddrThis);

 

 if(!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid))

   return ResultFromScode(SELFREG_R_TYPELIB);

 if(!COleObjectFactoryEx::UpdateRegistryAll(TRUE))

   return ResultFormScode(SELFREG_E_CLASS);

 

 if(FAILED (CreateComponentCategory(

     CATID_SafeForScripting,

     L"Controls that are safely scriptable")))

   return ResultFromScode(SELFREG_E_CLASS);

 

  if(FAILED (CreateComponentCategory(

     CATID_SafeForInitializing,

     L"Controls that are safely Initializable from persistent data")))

   return ResultFromScode(SELFREG_E_CLASS);

 

  if(FAILED( RegisterCLSIDInCategory(

    _ctlid, CATID_SafeForScripting)))

    return ResultFromScode(SELFREG_E_CLASS);

 

  if(FAILED( RegisterCLSIDInCategory(

    _ctlid, CATID_SafeForInitializing)))

    return ResultFromScode(SELFREG_E_CLASS);

                          

  return NOERROR;

}

 

이렇게 하면 컨트롤이 등록시 레지스트리에 이 컨트롤은 안전하다는 기록을 남기므로 IE는 더 이상 이를 문제삼지 않게 된다. 우리는 DllRegisterServer를 수정해 레지스트리에 몇 개의 키를 넣도록 수정했지만 DllUnregisterServer 함수에서 이를 제거하지는 않는다.

 

, Start컨트롤을 컴파일하고 코드사인하고 Cab으로 압축해 이를 웹서버에 올려 브라우저로 확인해 보자. 그럼 이제 안전하게 다운로드된 컨트롤을 볼 수 있을 것이다. 지금까지 완전한 Hello World 컨트롤을 제작했다고 생각하면 된다. 모든 것이 그렇듯이 Hello World를 얼마나 빨리 만드느냐가 프로젝트의 수행 시간을 좌우하게 된다. 그러나 이것만으로는 아직 시작에 불과하다.

 

사용자 삽입 이미지
 

컨트롤과 스크립트와의 대화

이 액티브X 컨트롤을 가지고 웹 상에서의 HTML 문서에서 어떤 것들이 가능할까. 또 어떻게 활용하는 것이 좋은 방안인지 생각해 보자.  IE에서 하나의 HTML은 여러가지 구성요소 그림1을 갖게 된다.


사용자 삽입 이미지
 

이들 각 구성요소간의 통신은 반드시 필요한 부분이다. 이들 컨트롤과 스크립트 엔진이 어떻게 서로 대화하는지 알아보자. 컨트롤은 자신을 노출하는 방법으로 프로퍼티, 메쏘드, 이벤트 세가지 방법을 제공하고 있다. 이들을 만드는 방법은 마소 과월호나 일반 서적에서 쉽게 찾아 볼 수 있다. Start 컨트롤에 다음의 프로퍼티, 메쏘드, 이벤트를 만들어보자.

 

프로퍼티 : CString MyName;   <- 컨트롤의 이름

메쏘드  :  BOOL CallMeIn10Seconds();   <- 10초후에 불러줄 것을 요구하는 메쏘드

이벤트 : void DidYouCallMe();   <- 발생되는 이벤트

 

프로퍼티

프로퍼티는 말 그대로 컨트롤의 특성을 지정하는 것으로 프로퍼티의 값을 설정하는 방법은 <OBJECT> 태그안에서 <PARAM> 태그를

이용하는 방법과 자바스크립트를 이용하는 방법이 있다. 다음 예를 보자.

 

1) <PARAM> 태그

 <OBJECT ID = "Start" WIDTH = 300 HEIGHT = 200

   classid = "clsid:63C4E7C7-5286-4003-95CF-CB29DE0173D3">

 <PARAM Name = "MyName" VALUE = "김범수">

 </OBJECT>

 

2) javascript

 <Script>

  Document.Start.MyName = "김범수";

 </Script>

 

 

컨트롤을 만들고 가장 많이 실수하는 부분이 DoPropExchange(CPropExchange * pPX) 함수 속성과 StartCtrl 클래스의 멤버변수와 데이터를 교환시켜 주는 부분을 잊는 경우이다. <PARAM> 태그를 사용해 초기값으로 지정한 경우 이 값은 단지 속성 영역에만 기록될 뿐 StartCtrl 클래스의 멤버변수에 들어오지 않는다. 멤버변수까지 이 값이 들어오게 하기 위해서는 개발자가 직접 다음과 같은 코드를 넣어주어야 한다.

void CStartCtrl::DoPropExchange(CProExchange * pPX)

{

  ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));

  COleControl::DoPropExchange(pPX);

  PX_String(pPX, _T("MyName"), m_strMyName,"");

}

 

메쏘드

메쏘드는 스크립트가 컨트롤에 무엇인가를 시키고자 할 때 사용한다. 따라서 우리가 만든

CallmeIn10Seconds()를 스크립트를 이용해 호출해 보자.

<Script>

  Document.Start.CallMeIn10Seconds();

</Script>

 

이벤트

이벤트는 메쏘드와 반대의 개념이다. 이것은 컨트롤이 무엇인가 특별한 일이 생겼음을 스크립트 엔진에 알리는 방법이다.

이벤트는 IE에서 아래와 같은 방법으로 사용할 수 있다.

<script for=Start event=DidYouCallMe() language = "JavaScript">

   alert(document.Start.MyName);

</script>

 

이 세가지 방법을 사용한 컨트롤과 스크립트를 완성해 보자(리스트3).


사용자 삽입 이미지

/*  위 리스트 3 그림 시작 */
/////////////////////////////////////////////////////////////////////////////
// CStartCtrl::OnDraw - Drawing function

void CStartCtrl::OnDraw(
   CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
 // TODO: Replace the following code with your own drawing code.
 pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
 pdc->Rectangle(rcBounds);
 pdc->TextOut(10,10,"파일럿 콘트롤입니다.");
}


/////////////////////////////////////////////////////////////////////////////
// CStartCtrl::DoPropExchange - Persistence support

void CStartCtrl::DoPropExchange(CPropExchange* pPX)
{
 ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
 COleControl::DoPropExchange(pPX);

 // TODO: Call PX_ functions for each persistent custom property.
 PX_String(pPX , _T("MyName") , m_strMyName, "unknown");
}


/////////////////////////////////////////////////////////////////////////////
// CStartCtrl::OnResetState - Reset control to default state

void CStartCtrl::OnResetState()
{
 COleControl::OnResetState();  // Resets defaults found in DoPropExchange

 // TODO: Reset any other control state here.
}


/////////////////////////////////////////////////////////////////////////////
// CStartCtrl::AboutBox - Display an "About" box to the user

void CStartCtrl::AboutBox()
{
 CDialog dlgAbout(IDD_ABOUTBOX_START);
 dlgAbout.DoModal();
}


/////////////////////////////////////////////////////////////////////////////
// CStartCtrl message handlers

void CStartCtrl::OnMyNameChanged()
{
 // TODO: Add notification handler code

 SetModifiedFlag();
}

void CStartCtrl::CallMeIn10Seconds()
{
 // TODO: Add your dispatch handler code here
 SetTimer(0,10000,NULL); //10초뒤에 시간 발생
}

void CStartCtrl::OnTimer(UINT nIDEvent)
{
 // TODO: Add your message handler code here and/or call default
 KillTimer(0);
 FireDidYouCallMe();
 COleControl::OnTimer(nIDEvent);
}

/* 리스트3 내용 끝 */



그리고 Start.html(리스트4
아래 텍스트 타이핑)를 수정하고

화면 아래의 링크를 클릭하면 10초후에 화면5와 같은 재미있는 메시지를 보게 될 것이다.

 

<html>

<head>

<script for=Start event=DidYouCallme() language="JavaScript">

<!--

  alert("WhyDidYouCallME("+document.Start.MyName+")?");

//-->

</script>

</head>

 

<body>

 <OBJECT ID = "Start" WIDTH = 300 HEIGHT = 200

   classid = "clsid:63C4E7C7-5286-4003-95CF-CB29DE0173D3">

 <PARAM Name = "MyName" VALUE = "KBS">

 </OBJECT>

<br>

<a herf="JavaScript:document.Start.CallMeIn10Seconds()">Please Call Me In 10 Seconds</a>

</body>

</html>

--------------- 위 내용 리스트4 -----------------------------

 


사용자 삽입 이미지
 

 

다음 시간에는

이상으로 우리는 하나의 완성된 컨트롤과 이것을 HTML 문서에서 어떻게 사용할 수 있는지를 알아보았다. 이것만으로도 MFC다룰 수 있는 개발자라면 웬만한 컨트롤을 직접 만들고 배포하는 데 어려움은 없을 것이다. 이번호에서는 전체적인 윤곽을 이해하기 위해 전반적인 이야기를 했기 때문에 쉽게 이해했으리라 생각된다. 다음호에서는 좀더 IE속에 들어가서 아주 재미있고 중요한 주제들을 갖고 이야기하려 한다IE의 구조를 이해하고 IE에서 컨트롤의 두 가지 상태(Acitive Inactive)에 대해 이해하게 될 것이다.

컨트롤의 이 두가지 상태 때문에 IE에서 돌아가는 컨트롤을 제작하다 보면 MFC 일반 응용프로그램 개발과는 다른 부분들을 접하게 된다. 이러한 부분들을 알아보고 원인은 무엇이며 어떻게 처리해야 하는지 살펴보기로 하자.


소스 파일은 이달의 디스켓 start.zip을 참조한다.