이벤트 추가(ATL 자습서, 5부)
이 단계에서는 ATL 컨트롤에 ClickOut
a ClickIn
및 이벤트를 추가합니다. 사용자가 다각형 내에서 클릭하면 이벤트가 발생 ClickIn
하며 사용자가 외부를 클릭하면 발생 ClickOut
합니다. 이벤트를 추가하는 작업은 다음과 같습니다.
및
ClickIn
ClickOut
메서드 추가형식 라이브러리 생성
커넥트ion Point 인터페이스 구현
ClickIn 및 ClickOut 메서드 추가
2단계에서 ATL 컨트롤을 만들 때 커넥트온점 검사 상자를 선택했습니다. Polygon.idl 파일에서 인터페이스를 만들었습니다 _IPolyCtlEvents
. 인터페이스 이름은 밑줄로 시작합니다. 인터페이스가 내부 인터페이스임을 나타내는 규칙입니다. 따라서 COM 개체를 찾아볼 수 있는 프로그램은 사용자에게 인터페이스를 표시하지 않도록 선택할 수 있습니다. 또한 커넥트이온 지점을 선택하면 Polygon.idl 파일에 다음 줄이 추가되어 기본 소스 인터페이스임을 _IPolyCtlEvents
나타냅니다.
[default, source] dispinterface _IPolyCtlEvents;
원본 특성은 컨트롤이 알림의 원본임을 나타내므로 컨테이너에서 이 인터페이스를 호출합니다.
이제 인터페이스에 ClickIn
및 ClickOut
메서드를 추가합니다 _IPolyCtlEvents
.
ClickIn 및 ClickOut 메서드를 추가하려면
솔루션 탐색기 Polygon.idl을 열고 PolygonLib 라이브러리 선언 아래에
methods:
dispInterface_IPolyCtlEvents
다음 코드를 추가합니다.[id(1), helpstring("method ClickIn")] void ClickIn([in] LONG x,[in] LONG y); [id(2), helpstring("method ClickOut")] void ClickOut([in] LONG x,[in] LONG y);
및 ClickOut
메서드는 ClickIn
클릭한 점의 x 및 y 좌표를 매개 변수로 사용합니다.
형식 라이브러리 생성
이 시점에서 형식 라이브러리를 생성합니다. 프로젝트가 이를 사용하여 연결점 인터페이스 및 컨트롤에 대한 연결점 컨테이너 인터페이스를 생성하는 데 필요한 정보를 가져오기 때문입니다.
형식 라이브러리를 생성하려면
프로젝트를 다시 빌드합니다.
또는
솔루션 탐색기 Polygon.idl 파일을 마우스 오른쪽 단추로 클릭하고 바로 가기 메뉴에서 컴파일을 클릭합니다.
이렇게 하면 형식 라이브러리인 Polygon.tlb 파일이 만들어집니다. Polygon.tlb 파일은 이진 파일이며 직접 보거나 편집할 수 없으므로 솔루션 탐색기 표시되지 않습니다.
커넥트ion Point 인터페이스 구현
컨트롤에 대한 연결점 인터페이스 및 연결점 컨테이너 인터페이스를 구현합니다. COM에서 이벤트는 연결 지점의 메커니즘을 통해 구현됩니다. COM 개체에서 이벤트를 수신하기 위해 컨테이너는 COM 개체가 구현하는 연결 지점에 대한 권고 연결을 설정합니다. COM 개체에는 여러 연결점이 있을 수 있으므로 COM 개체는 연결점 컨테이너 인터페이스도 구현합니다. 이 인터페이스를 통해 컨테이너는 지원되는 연결점을 결정할 수 있습니다.
연결점을 구현하는 인터페이스를 호출 IConnectionPoint
하고 연결점 컨테이너를 구현하는 인터페이스를 호출 IConnectionPointContainer
합니다.
구현IConnectionPoint
을 돕기 위해 커넥트 구현 지점 마법사를 사용합니다. 이 마법사는 형식 라이브러리를 IConnectionPoint
읽고 실행할 수 있는 각 이벤트에 대한 함수를 구현하여 인터페이스를 생성합니다.
연결점을 구현하려면
솔루션 탐색기 _IPolyCtlEvents_CP.h를 열고 클래스의
public:
문CProxy_IPolyCtlEvents
아래에 다음 코드를 추가합니다.VOID Fire_ClickIn(LONG x, LONG y) { T* pT = static_cast<T*>(this); int nConnectionIndex; CComVariant* pvars = new CComVariant[2]; int nConnections = m_vec.GetSize(); for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++) { pT->Lock(); CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex); pT->Unlock(); IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p); if (pDispatch != NULL) { pvars[1].vt = VT_I4; pvars[1].lVal = x; pvars[0].vt = VT_I4; pvars[0].lVal = y; DISPPARAMS disp = { pvars, NULL, 2, 0 }; pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL); } } delete[] pvars; } VOID Fire_ClickOut(LONG x, LONG y) { T* pT = static_cast<T*>(this); int nConnectionIndex; CComVariant* pvars = new CComVariant[2]; int nConnections = m_vec.GetSize(); for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++) { pT->Lock(); CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex); pT->Unlock(); IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p); if (pDispatch != NULL) { pvars[1].vt = VT_I4; pvars[1].lVal = x; pvars[0].vt = VT_I4; pvars[0].lVal = y; DISPPARAMS disp = { pvars, NULL, 2, 0 }; pDispatch->Invoke(0x2, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL); } } delete[] pvars; }
이 파일에는 파생되는 클래스 CProxy_IPolyCtlEvents
가 있습니다 IConnectionPointImpl
. 이제 _IPolyCtlEvents_CP.h는 두 개의 메서드 Fire_ClickIn
를 정의하고 Fire_ClickOut
두 개의 좌표 매개 변수를 사용합니다. 컨트롤에서 이벤트를 실행하려는 경우 이러한 메서드를 호출합니다.
커넥트ion points 옵션이 선택된 컨트롤을 만들어 _IPolyCtlEvents_CP.h 파일이 생성되었습니다. 또한 COM 맵에 적절한 항목을 추가하여 컨트롤의 여러 상속 목록에 추가하고 CProxy_PolyEvents
IConnectionPointContainerImpl
노출 IConnectionPointContainer
합니다.
이벤트를 지원하는 코드 구현이 완료되었습니다. 이제 적절한 순간에 이벤트를 발생하도록 몇 가지 코드를 추가합니다. 사용자가 컨트롤의 ClickIn
왼쪽 마우스 단추를 클릭하면 이벤트나 ClickOut
이벤트가 발생합니다. 사용자가 단추를 클릭하는 시기를 확인하려면 메시지에 대한 처리기를 추가합니다 WM_LBUTTONDOWN
.
WM_LBUTTONDOWN 메시지에 대한 처리기를 추가하려면
클래스 뷰에서 클래스를 마우스 오른쪽 단추로
CPolyCtl
클릭하고 바로 가기 메뉴에서 속성을 클릭합니다.속성 창에서 메시지 아이콘을 클릭한 다음 왼쪽의 목록에서 클릭합니다
WM_LBUTTONDOWN
.표시되는 드롭다운 목록에서 OnLButtonDown 추가를 클릭합니다<.> 처리기 선언이
OnLButtonDown
PolyCtl.h에 추가되고 처리기 구현이 PolyCtl.cpp에 추가됩니다.
다음으로 처리기를 수정합니다.
OnLButtonDown 메서드를 수정하려면
다음과 같이 보이도록 PolyCtl.cpp의 메서드를 구성하는
OnLButtonDown
코드를 변경합니다(마법사에서 배치한 모든 코드 삭제).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; }
이 코드는 함수에서 계산된 OnDraw
점을 사용하여 호출 PtInRegion
을 통해 사용자의 마우스 클릭을 감지하는 영역을 만듭니다.
uMsg 매개 변수는 처리 중인 Windows 메시지의 ID입니다. 이렇게 하면 메시지 범위를 처리하는 하나의 함수를 사용할 수 있습니다. wParam 및 lParam 매개 변수는 처리 중인 메시지에 대한 표준 값입니다. 매개 변수 bHandled 를 사용하면 함수가 메시지를 처리했는지 여부를 지정할 수 있습니다. 기본적으로 값은 함수가 메시지를 처리했음을 나타내기 위해 TRUE로 설정되지만 FALSE로 설정할 수 있습니다. 이로 인해 ATL은 메시지를 보낼 다른 메시지 처리기 함수를 계속 찾습니다.
컨트롤 빌드 및 테스트
이제 이벤트를 사용해 보세요. 컨트롤을 빌드하고 ActiveX 컨트롤 테스트 컨테이너를 다시 시작합니다. 이번에는 이벤트 로그 창을 봅니다. 이벤트를 출력 창으로 라우팅하려면 옵션 메뉴에서 로깅을 클릭하고 출력 창에 로그를 선택합니다. 컨트롤을 삽입하고 창에서 클릭해 봅니다. ClickIn
채워진 다각형 내에서 클릭하면 발생하며 ClickOut
외부를 클릭하면 발생합니다.
다음으로 속성 페이지를 추가합니다.