ATL ActiveX
Control 만들기

Step 1.

1. ATL 프로젝트를
생성한다.<?xml:namespace prefix = o
/>

생성시 서버의 DLL

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml"
/><?xml:namespace prefix = v /><?xml:namespace prefix = v
/><?xml:namespace prefix = v />

2. 응용프로그램
설정에서 서버 유형을 동적
링크라이브러리(DLL)로
한다. 기본으로 설정되어
있음

Step 2.

1. 프로젝트에서
마우스 오른쪽 클릭 후, 추가에서 클래스를
선택한다.

2. 클래스 추가
다이얼로그에서 ATL 범주의 ATL 컨트롤 템플릿을
선택하고 추가를 누른다.

약식 이름에 PolyCtl을 입력한다.

그리고 몇 가지 추가적인
설정이 필요하다.

3. 풍부한 에러
정보와 연결 지점에 대한
지원을 위해

- 옵션에서 지원: 연결지점을
체크한다.

4. 컨트롤을
삽입 가능하게 만들기 위해(컨트롤을 삽입 가능하게
만든다는 말은 삽입 객체를
지원하는 엑셀이나 워드
같은 애플리케이션에 삽입할
수 있다는 말을 뜻한다.)

- 모양에서 기타: 삽입가능을
체크한다.

5. 채우기 색상
스톡 속성을 추가하고 컨트롤을
생성하기 위해(여기서
만든 객체에 의해 보여지는
폴리곤은 solid 채우기
색을 가지고 있으므로 채우기
컬러를 설정하기 위해 색상
스톡 옵션을 설정한다)

- 스톡 속성의 지원하지
않음 리스트에서
FillColor를 선택하고 지원에
추가한다.

6. 그리고 마침을
누른다.

그러면 다음과 같은 파일들이
추가된다.

File

Description

PolyCtl.h

Contains most of the
implementation of the C++ class CPolyCtl.

PolyCtl.cpp

Contains the remaining
parts of CPolyCtl.

PolyCtl.rgs

A text file that
contains the registry script used to register the control.

PolyCtl.htm

A Web page containing
a reference to the newly created control.

방금 실행한 위자드는
다음과 같은 코드 변경을
수행한다.

- 컨트롤 지원을
위해 필요한 ATL 파일
추가하기 위하여
Stdafx.h와 stdafx.cpp  파일에 #include 문을 추가한다.

- 새로운 컨트롤에
대한 세부 사항을 포함하기
위해 Polygon.i이 파일을
수정한다.

- Polygon.cpp의 객체
맴에 새로운 컨트를을 추가한다.

7. 이제 빌드하고
테스트 해볼 수 있다.

- Build 메뉴에서 Build Polygon을 클릭하여 빌드
하고, PolyCtl.htm을 더블 클릭하면
컨트롤을 포함한 웹페이지를
볼 수 있다.

이제는 컨트롤에 속성을
더 추가한다.

Step 3: 속성을
컨트롤에 추가하기

1. 속성을 추가하기
위해 클래스 뷰의
PolyCtl 을 오른쪽 클릭하고
추가의 속성 추가를 선택한다.

2. 나타난 속성
창에서 속성 형식은 SHORT 속성 이름은 Sides로 입력하고 마침을 누른다.

인터페이스에 속성을 추가할
때, MIDL ( idl 파일을 컴파일하는
프로그램 ) 은 GET/PUT 메소드를 정의 한다. 메소드 이름은 put_과 get_이 앞에
붙게 된다.

/*속성 추가
위자드는 idl 파일에
필요한 라인을 추가하며 PolyCtl.h의 클래스 정의에
함수 프로토타입을 추가하며 PolyCtl.cpp에 빈 구현을 추가한다. 현재 생성한 함수의
이름은 get_Sides/put_Sides이다.

이제 생성된 get_/put_ 함수는
속성을 저장하고 다루기
위해 적절히 구현하여야
한다. */

3. 소스 코드
추가

- PolyCtl.h 의 멤버
변수로 short m_nSides; 을 추가한다. m_clrFillColor
다음에 추가하면
됨.

- PolyCtl 클래스의
생성자에 m_nSides = 3 을 추가한다. 이는 삼각형을 나타냄

- get_/put_ 메소드를
구현한다. 선언은 PolyCtl.h 에 이미 있으며, PolyCtl.cpp 에 다음 구현 코드를
추가한다.

STDMETHODIMP CPolyCtl::get_Sides(short*
pVal)

{

*pVal = m_nSides;

return S_OK;

}

STDMETHODIMP CPolyCtl::put_Sides(short
newVal)

{

if (2 < newVal && newVal < 101)

{

m_nSides = newVal;

return S_OK;

}

else

{

return Error(_T("Shape
must have between 3 and 100 sides"));

}

}

Step 4: 그리기
코드 수정

기본적으로 컨트롤의 그리기
코드는 ATL 8.0 : PolyCtl 텍스트를
사각형 내에 출력한다. 이제 이 코드를 수정하여
새로운 그리기가 가능하도록
한다.

1, PolyCtl.h 에 #include <math.h> 를 차가하고, 클래스의 마지막에
폴리곤 포인트를 저장할 POINT 형 변수 배열 POINT m_arrPoint[100]을 추가한다.

2. 실제 그리기를
수행하는 OnDraw 메소드를
수정한다.

HRESULT CPolyCtl::OnDraw(ATL_DRAWINFO& di)

{

RECT& rc =
*(RECT*)di.prcBounds;

HDC hdc  = di.hdcDraw;

COLORREF    colFore;

HBRUSH      hOldBrush,
hBrush;

HPEN
hOldPen, hPen;

// Translate m_colFore into a COLORREF type

OleTranslateColor(m_clrFillColor,
NULL, &colFore);

// Create and select the colors to draw the circle

hPen =
(HPEN)GetStockObject(BLACK_PEN);

hOldPen =
(HPEN)SelectObject(hdc, hPen);

hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);

hOldBrush =
(HBRUSH)SelectObject(hdc, hBrush);

Ellipse(hdc, rc.left,
rc.top, rc.right, rc.bottom);

// Create and select the brush that will be used to fill
the polygon

hBrush    = CreateSolidBrush(colFore);

SelectObject(hdc,
hBrush);

CalcPoints(rc);

Polygon(hdc,
&m_arrPoint[0], m_nSides);

// Select back the old pen and brush and delete the brush
we created

SelectObject(hdc,
hOldPen);

SelectObject(hdc,
hOldBrush);

DeleteObject(hBrush);

return S_OK;

}

3. Polygon을 그리기 위한 포인트를
계산하는 메소드를 만든다.

PolyCtl.h 에 다음과 같이 정의
하고

public:

STDMETHOD(get_Sides)(short* pVal);

STDMETHOD(put_Sides)(short newVal);

void
CalcPoints(const RECT& rc);

PolyCtl.cpp에 구현을 한다.

void
CPolyCtl::CalcPoints(const RECT& rc)

{

const double pi =
3.14159265358979;

POINT   ptCenter;

double  dblRadiusx
= (rc.right - rc.left) / 2;

double
dblRadiusy = (rc.bottom - rc.top) / 2;

double
dblAngle = 3 * pi / 2;
// Start at the top

double
dblDiff  = 2 * pi /
m_nSides;   // Angle each side will make

ptCenter.x = (rc.left
+ rc.right) / 2;

ptCenter.y = (rc.top
+ rc.bottom) / 2;

// Calculate the points for each side

for (int i = 0; i
< m_nSides; i++)

{

m_arrPoint[i].x = (long)(dblRadiusx *
cos(dblAngle) + ptCenter.x + 0.5);

m_arrPoint[i].y
= (long)(dblRadiusy * sin(dblAngle) +
ptCenter.y + 0.5);

dblAngle += dblDiff;

}

}

그리고, 생성자에
기본 컬러를 설정한다.

CPolyCtl()

{

m_nSides = 3;

m_clrFillColor = RGB(0, 0xFF, 0);

}

지금까지의 결과를 Build하고 다시
PolyCtl.htm을 브라우져에서 열면
연두색으로 설정된 삼각이
나온다. 메소드 호출에
의해 색이 변하는 것은 put 메소드에
FireViewChange를 추가한다.

m_Sides 나 m_clrFillColor 값을 바꾸었을
때, 적용 시키려면 FireViewChange() 를 호출한다.

STDMETHODIMP CPolyCtl::put_Sides(short
newVal)

{

if (2 < newVal && newVal < 101)

{

m_nSides = newVal;

FireViewChange();

return S_OK;

}

else

{

return Error(_T("Shape
must have between 3 and 100 sides"));

}

}

그리고, 비쥬얼
스튜디오 도구의
ActiveX Control Test Container를 실행하고

ActiveX Control Test Container 의 편집 새컨트롤 삽입에서 PolyCtl을 선택하고, 컨트롤에서 메서드
호출을 클릭하면 메서드
호출 창이 나오는데 여기서 Sides(PropPut)을 선택하고 파라이터를
입력하고 호출을 누르면
색이 바뀜을 볼 수 있다.

Step 5: 이벤트
추가

추가할 이벤트는
ClickIn, ClickOut 이다. 폴리곤
내에서 사용자의 클릭이
있으면 ClickIn, 폴리곤
밖에서 클릭이 일어나면 ClickOut 이벤트를 발생시킨다. 해야 할 일 들은 다음과
같은 일이다.

- ClickIn, ClickOut 메소드를
추가

- Type Library를 생성

- Connection Point Interface를 구현

메소드
추가하기

1. 클래스뷰의 PolygonLib 하의
Lib_IPolyCtlEvent에서 마우스 오른쪽
클릭 후 추가에서 메소드
추가를 선택한다.

2. 반환 형식은 void, 매개변수 타입은 long, 함수 이름은 ClickIn, 매개변수 이름은 x로 한다.

3. 매개변수
이름아래의 추가를 누르고, 매개변수 이름을 y로 해서 또 추가한다.

4. ClickOut 함수에
대해서도 같은 방식으로
반복한다.

그러면, Polygon.idl 파일에
다음 코드가 추가된다.

dispinterface
_IPolyCtlEvents

{

properties:

methods:

[id(1), helpstring("메서드CheckIn")] void
ClickIn([in] LONG x, [in] LONG y);

[id(2), helpstring("메서드CheckOut")] void ClickOut([in]
LONG x, [in] LONG y);

};

Type Library

Connection Point 위자드는
이 컨트롤에 대한
Connection Point Interface 와 Connection Point
Container 를 생성하기 위해 필요한
정보를 얻기 위해 타입 라이브러리를
사용하므로 타입 라이브러리를
생성한다.

1. 프로젝트를
다시 빌드함

2. 또는, Polygon.idl 파일을 오른쪽
클릭하고 Compile 을 선택한다.

그러면 Polygon.tlb 파일이
생성되는데 이 파일이 타입
라이브러리이다.

Connection
Point Interface

Connection Point Interface와 Connection Point Container Interface 를 구현함

COM 에서 이벤트는 connection point 메커니즘을 통해
구현 된다. 이벤트를 COM 객체로부터 받기
위해 컨테이너는 COM 객체의 Connection Point 에 연결한다. COM 객체는 여러 개의 Connection Point 를 가지고 있지만
하나의 Connection Point Inteface를
구현한다. 컨테이너는
이 인터페이스를 통해 어떤 Connection Point 가 지원되는지
결정할 수 있다.

Connection Point를 구현한
인터페이스는
IConnectionPoint 를 통해 호출되고 Connection Point Container를 구현한 인터페이스를 IConnectionPointContainer를 통해 호출된다.

IConnectionPoint를 구현하는데 Connection Point를 위자드를 사용하는데
이 위자드는 타입 라이브러리를
읽고 IConnectionPoint를 생성한다. 그리고 각 이벤트를
구현한다.

1. 크래스 뷰의 CPolyCtl 에서 마우스 오른쪽
클릭, 추가, 연결
지점 추가를 선택한다.

2. 소스 인터페이스의 _IPolyCtlEvent를 연결지점 구현에
추가하고 마침 클릭한다.

3. 그러면 Connection Point에 대한 프록시
클래스가 생성되는데, 그 클래스는CProxy_IPolyCtlEvents 이다.

생성된 _IPolyCtlEvents_CP.h 파일을
보면 IConnectionPointImpl을 상속한
CProxy_IPolyCtlEvents 클래스를 볼
수 있다. 또한, 이 클래스는
Fire_ClickIn, Fire_ClickOut 메소드를 정의한다. 만든 콘트롤에 인벤트를
발생시키길 원한다면 이
메소드를 호출하면 된다.

위자드는 CProxy_IPolyCtlEvents 와
IConnectionPointContainerImpl을 컨트롤의 multiple inheritance list 에 추가한다. 또한 IConnectionPointContainer을 COM 맵의 적당한 엔트리에
추가한다.

마우스
이벤트 처리기 추가

CheckIn, CheckOut은 마우스
이벤트가 어디에서 일어났는지에
대한 처리를 목적으로 하므로
마우스 이벤트 처리를 위해 CPolyCtl 클래서에
WM_LBOTTONDOWN 메시지 처리 메소드를
추가한다.

LRESULT CPolyCtl::OnLButtonDown(UINT /*uMsg*/,
WPARAM /*wParam*/, LPARAM lParam,

BOOL& /*bHandled*/)

{

HRGN hRgn;

WORD xPos =
LOWORD(lParam);  // horizontal position of cursor

WORD yPos = HIWORD(lParam);  // vertical
position of cursor

CalcPoints(m_rcPos);

// Create a region from our list of points

hRgn =
CreatePolygonRgn(&m_arrPoint[0], m_nSides, WINDING);

// If the clicked point is in our polygon then fire the
ClickIn

//  event
otherwise we fire the ClickOut event

if (PtInRegion(hRgn, xPos, yPos))

Fire_ClickIn(xPos, yPos);

else

Fire_ClickOut(xPos, yPos);

// Delete the region that we created

DeleteObject(hRgn);

return 0;

}

이 메소드에서는 폴리곤
영역 밖이라면
Fire_ClickOut을 호출하고 영역 안이면 Fire_ClickIn을 호출한다.

Build And
Test

새로 빌드하고 비쥬얼
스튜디오의 도구>ActiveX
Control Test Container를 선택한다.

ActiveX Control Test Container의 옵션>로깅>출력창에 로깅을
선택

편집 > 새컨트롤삽입
선택 > 다이얼로그의
리스트 박스에서
PolyCtl 선택 후 나타난 화면에서
마우스를 클릭해 본다.

- 추가 설명

이벤트 관련

CPolyCtl.h에 보면 이벤트를 위한 CONNECTION_POINT 엔트리로 _IPolyCtlEvents 가 설정 되어 있고

CPolyCtl.h

BEGIN_CONNECTION_POINT_MAP(CPolyCtl)

CONNECTION_POINT_ENTRY(__uuidof(_IPolyCtlEvents))

END_CONNECTION_POINT_MAP()

_IPolyCtlEvents_CP.h 에 CProxy_IPolyCtlEvents 클래스가
IConnectionPointImpl<T, &__uuidof(_IPolyCtlEvents)>을
상속하면서 _IPolyCtlEvents 을
템플릿으로 받음을 복수
잇다. _IPolyCtlEvents_CP.h 에는 pConnection->Invoke 를 통해 이벤트를
발생시키는데 Invoke 파라미터의
처음을 보면 1, 2 가
있다. 각 번호는 Polygon.idl의 id와 맵핑되며
해당 id의 메소드를
호출함을 알 수 있다.

Fire_ClickIN:  hr = pConnection->Invoke(1, IID_NULL, LOCALE_USER_DEFAULT,
DISPATCH_METHOD, &params, NULL, NULL, NULL);

Fire_ClickOut: hr =
pConnection->Invoke(2,
IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &params, NULL, NULL,
NULL);

Polygon.idl

dispinterface
_IPolyCtlEvents

{

properties:

methods:

[id(1),
helpstring("메서드CheckIn")] void ClickIn([in] LONG x, [in] LONG y);

[id(2),
helpstring("메서드CheckOut")] void ClickOut([in] LONG x, [in]
LONG y);

};

메소드
관련

CPolyCtl.h 의 STDMETHOD는 Polygon.idl의 propget/progput 과 연관 된다.

CPolyCtl.h

STDMETHOD(get_Sides)(short* pVal);

STDMETHOD(put_Sides)(short newVal);

Polygon.idl

[propget
id(1) helpstring("속성Sides")] HRESULT Sides([out retval] SHORT* pVal);

[propput id(1)
helpstring("속성Sides")] HRESULT Sides([in] SHORT newVal);

Step 6: 속성 페이지
추가

속성 페이지는 분리된 COM 객체로 구현된다. 이 단계에서는 컨트롤에
속성 페이지를 추가하기
위해 다음과 같은 일은 한다.

- 속성 페이지
리소스 생성

- 속성 페이지를
생성하고 관리하는 코드
추가

- 컨트롤에
속성 페이지 추가

속성 페이지
생성

1. 프로젝트의
오른쪽 클릭>추가>클래스 에서 ATL 속성 페이지를 선택한다.

2. 약식 이름에 PolyProp를 입력한다.

3. 스트링의
제목에 &Polygon 을 입력하고
마침

다음과 같은 파일이 생성된다.

File

Description

PolyProp.h

Contains the C++ class CPolyProp, which implements the
property page.

PolyProp.cpp

Includes the PolyProp.h file.

PolyProp.rgs

The registry script that registers the property page object.

속성 페이지에
필드 추가

1. 프로젝트의 Polygon.rc 리소스 파일의 Dialog 에서 IDD_POLYPROP 를
클릭한다.

2. 리소스 창에
나오는 다이얼로그에 정적
문자열과 에디트 컨트롤을
추가한다.

3. 에디트 컨트롤의 ID를 ID_SIDES로 수정한다.

속성 페이지를
생성하고 관리할 코드 추가

속성 페이지의 Apply 버튼을
눌렀을 때, 입력된
속성을 적용하기 위해 Apply 메소드를 수정한다.

1. PolyProps.h 파일의 Apply 메소드를 수정한다.

STDMETHOD(Apply)(void)

{

USES_CONVERSION;

ATLTRACE(_T("CPolyProp::Apply\n"));

for
(UINT i = 0; i < m_nObjects; i++)

{

CComQIPtr<IPolyCtl,
&IID_IPolyCtl> pPoly(m_ppUnk[i]);

short
nSides = (short)GetDlgItemInt(IDC_SIDES);

if FAILED(pPoly->put_Sides(nSides))

{

CComPtr<IErrorInfo> pError;

CComBSTR strError;

GetErrorInfo(0, &pError);

pError->GetDescription(&strError);

MessageBox(OLE2T(strError), _T("Error"), MB_ICONEXCLAMATION);

return
E_FAIL;

}

}

m_bDirty = FALSE;

return
S_OK;

}

Apply 버튼을
가능하게 하기

사용자가 Sides 에 값을
입력했을 때, Apply 버튼을
가능하게 하기 위해서 SetDirty(TRUE); 를 호출하여야
한다.

1, 클래스 뷰에서 CPolyProp의 속성을 연다.

2. 속성의 이벤트
항목에서 이벤트를 선택하고, IDD_SIDES 를 확장하고 EN_CHANGE 이벤트에 OnEnChangeSides 이름으로 이벤트
핸들러를 추가한다.

3. 추가된 이벤트
핸들러 코드를 다음과 같이
수정한다. (PolyProp.cpp)

LRESULT CPolyProp::OnEnChangeSides(WORD /*wNotifyCode*/,

WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)

{

SetDirty(TRUE);

return 0;

}

속성 페이지를
컨트롤에 추가

1. PolyCtl.h 의 속성
맵에 다음을 추가한다.

PROP_ENTRY("Sides", 1, CLSID_PolyProp)

빌드와 테스트

1. 프로젝트를
빌드하고 ActiveX Control Test
Container 에서 PolyCtl 을 연다.

2. 편집>PolyCtl 개체를 선택하면
속성 페이지가 나오고, 속성 페이지의 Sides 탭을 열면 만들었던
속성 페이지가 나온다.

3. 에디트에
값을 입력하면 적용(A) 버튼이 활성화되고
버튼을 누르면 폴리곤 모양이
바뀐다.

Step 6: 웹페이지에
추가하기

PolyCtl.h 에 아래 Bold 표시된 VB스크립트
코드를 추가한다.

<HTML><HEAD><TITLE>PolyCtl 개체에대한ATL 8.0 테스트페이지</TITLE></HEAD>

<BODY>

<OBJECT ID="PolyCtl" CLASSID="CLSID:E6F39BAE-7BFE-4F04-9C00-205C9A6A99C7"></OBJECT>

<SCRIPT LANGUAGE="VBScript">

<!--

Sub
PolyCtl_ClickIn(x, y)

PolyCtl.Sides = PolyCtl.Sides + 1

End Sub

Sub
PolyCtl_ClickOut(x, y)

PolyCtl.Sides = PolyCtl.Sides - 1

End Sub

-->

</SCRIPT>

</BODY>

</HTML>

IObjectSafetyImpl
를 컨트롤에
추가함

아래 코드를 PolyCtl.h 의 CPolyCtl 클래스의 상속 라인의
마지막에 추가하고

public IObjectSafetyImpl<CPolyCtl, INTERFACESAFE_FOR_UNTRUSTED_CALLER>

COM 맵에 다음
코드를 추가한다.

COM_INTERFACE_ENTRY(IObjectSafety)

TEST

PolyCtl.htm 을 웹브라우저에
열고, 폴리곤 안쪽을
클릭하면 각이 증가 밖을
클릭하면 각이 감소한다.

ATL ActiveX
Control 을 애플리케이션에서
사용 하기

Step1

1. MFC 애플리케이션
프로젝트를 만든다.

2, 리소스에서
다이얼로그 리소스를 연다.

3. 열려진 리소스에서
마우스 오른쪽 클릭하고 ActiveX Control 삽입을 선택한다.

4. 열린 다이얼로그의 ActiveX 리스트 중
PolyCtl 을 선택한다.

5. PolyCtl을 선택하면
다이얼로그 박스에 PolyCtl이 추가된다.

6. 추가된 PolyCtl 위에서 마우스 오른쪽
클릭하고 변수 추가를 누른다. PolyCtl에 대한 컨트롤 변수명으로 m_PolyCtl 을 입력한다.

7. 다음과 같이
컨트롤들을 만든다.

<?xml:namespace prefix = v ns =
"urn:schemas-microsoft-com:vml" />

8. Edit Box의 ID: IDC_SIDENUM , APPLY 버튼의 ID: IDC_BUTTON, Change Color 버튼의 ID: IDC_BUTTON2 로 한다.

9. APPLY 버튼의
컨트롤 이벤트 BN_CLICKED 에
대한 OnBnClickedButton 메소드를
만든다.

10. 이 메소드에서는 Edit Box의 값을 읽어 PolyCtl ActiveX 컨트롤에 값을
전달하여 폴리곤의 모양을
바꾸게 된다.

void
CTestPolyCtlAppDlg::OnBnClickedButton()

{

short sidenumber = this->GetDlgItemInt(IDC_SIDENUM,
NULL, FALSE);

m_PolyCtl.put_Sides(sidenumber);

}

메소드 호출은 단순히 put_ 또는 get_ 함수를
이용하게 된다.

11. Change Color 버튼의
컨트롤 이벤트 BN_CLICKED 에
대한 OnBnClickedButton2 메소드를
만든다.

12. 이 메소드에서는
폴리곤의 색을 바꾸기 위해
색선택 다이얼로그를 띄우고
색을 선택한 후, PolyCtl
ActiveX Control에 값을 전달하여
폴리곤 색을 바꾼다.

void
CTestPolyCtlAppDlg::OnBnClickedButton2()

{

CColorDialog
dlg;

if(dlg.DoModal() == IDOK ) {

m_PolyCtl.put_FillColor(dlg.GetColor());

}

}

<?xml:namespace prefix = o ns =
"urn:schemas-microsoft-com:office:office" />

Step2 : ATL
ActiveX Control의 이벤트 처리

PolyCtl에 대한
이벤트 처리는 다른 보통
컨트롤의 이벤트 처리 형식과
같다

1. 리소스 뷰의
다이얼 로그에서 삽입된 PolyCtl 위헤서 마우스 오른쪽
클린하고 속성을 연다.

2. 열린 속성에서
컨트롤 이벤트 탭을 열면 ClickIn 과 ClickOut 이벤트가
보인다.

3. 각각에 대해
이벤트 처리함 수를 만들면 PolyCtl에서 발생한 ClickIn/ClickOut 이벤트를 받을
수 있다. 이벤트 메소드를
각각 ClickInPolyctl/ ClickOutPolyctl 이라 하면
다음과 같이 작성할 수 있다.

void
CTestPolyCtlAppDlg::ClickInPolyctl(long x, long y)

{

TCHAR
text[50];

swprintf_s(text,
50, TEXT("ClickIn: X=%d, y=%d"),
x, y);

MessageBox(text,
L"ActiveX Control Event", MB_OK);

}

void CTestPolyCtlAppDlg::
ClickOutPolyctl(long x, long y)

{

TCHAR
text[50];

swprintf_s(text,
50, TEXT("ClickOut: X=%d, y=%d"),
x, y);

MessageBox(text,
L"ActiveX Control Event", MB_OK);

}

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml"
/>