// TestActiveX2Ctrl.cpp : CTestActiveX2Ctrl ActiveX 컨트롤 클래스의 구현입니다.

#include "stdafx.h"
#include "TestActiveX2.h"
#include "TestActiveX2Ctrl.h"
#include "TestActiveX2PropPage.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#endif


IMPLEMENT_DYNCREATE(CTestActiveX2Ctrl, COleControl)
// Interface map for IObjectSafety



// Interface map for IObjectSafety
BEGIN_INTERFACE_MAP( CTestActiveX2Ctrl, COleControl )
INTERFACE_PART(CTestActiveX2Ctrl, IID_IObjectSafety, ObjSafe)
END_INTERFACE_MAP()

// 메시지 맵입니다.

BEGIN_MESSAGE_MAP(CTestActiveX2Ctrl, COleControl)
	ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
END_MESSAGE_MAP()



// 디스패치 맵입니다.

BEGIN_DISPATCH_MAP(CTestActiveX2Ctrl, COleControl)
	DISP_FUNCTION_ID(CTestActiveX2Ctrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()



// 이벤트 맵입니다.

BEGIN_EVENT_MAP(CTestActiveX2Ctrl, COleControl)
END_EVENT_MAP()



// 속성 페이지입니다.

// TODO: 필요에 따라 속성 페이지를 추가합니다. 카운트도 이에 따라 증가해야 합니다.
BEGIN_PROPPAGEIDS(CTestActiveX2Ctrl, 1)
	PROPPAGEID(CTestActiveX2PropPage::guid)
END_PROPPAGEIDS(CTestActiveX2Ctrl)



// 클래스 팩터리와 GUID를 초기화합니다.

IMPLEMENT_OLECREATE_EX(CTestActiveX2Ctrl, "TESTACTIVEX2.TestActiveX2Ctrl.1",
	0x72c74757, 0xefca, 0x4e60, 0x86, 0xb1, 0xc, 0x74, 0xca, 0x32, 0x7c, 0x16)



// 형식 라이브러리 ID와 버전입니다.

IMPLEMENT_OLETYPELIB(CTestActiveX2Ctrl, _tlid, _wVerMajor, _wVerMinor)



// 인터페이스 ID입니다.

const IID BASED_CODE IID_DTestActiveX2 =
		{ 0xF7BE4178, 0x149, 0x4788, { 0x8D, 0xF9, 0x97, 0xE7, 0xCF, 0xB3, 0x7F, 0x70 } };
const IID BASED_CODE IID_DTestActiveX2Events =
		{ 0x7F24043D, 0x2045, 0x4B92, { 0xB6, 0xC6, 0xE8, 0xB3, 0xC7, 0x17, 0xEF, 0x6 } };



// 컨트롤 형식 정보입니다.

static const DWORD BASED_CODE _dwTestActiveX2OleMisc =
	OLEMISC_ACTIVATEWHENVISIBLE |
	OLEMISC_SETCLIENTSITEFIRST |
	OLEMISC_INSIDEOUT |
	OLEMISC_CANTLINKINSIDE |
	OLEMISC_RECOMPOSEONRESIZE;

IMPLEMENT_OLECTLTYPE(CTestActiveX2Ctrl, IDS_TESTACTIVEX2, _dwTestActiveX2OleMisc)



// CTestActiveX2Ctrl::CTestActiveX2CtrlFactory::UpdateRegistry -
// CTestActiveX2Ctrl에서 시스템 레지스트리 항목을 추가하거나 제거합니다.

STDMETHODIMP_(ULONG) CTestActiveX2Ctrl::XObjSafe::AddRef()
{
	METHOD_PROLOGUE_EX_(CTestActiveX2Ctrl, ObjSafe)
		return (ULONG)pThis->ExternalAddRef();
}

STDMETHODIMP_(ULONG) CTestActiveX2Ctrl::XObjSafe::Release()
{
	METHOD_PROLOGUE_EX_(CTestActiveX2Ctrl, ObjSafe)
		return (ULONG)pThis->ExternalRelease();
}

STDMETHODIMP CTestActiveX2Ctrl::XObjSafe::QueryInterface(
	REFIID iid, LPVOID* ppvObj)
{
	METHOD_PROLOGUE_EX_(CTestActiveX2Ctrl, ObjSafe)
		return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
}



const DWORD dwSupportedBits =
INTERFACESAFE_FOR_UNTRUSTED_CALLER |
INTERFACESAFE_FOR_UNTRUSTED_DATA;
const DWORD dwNotSupportedBits = ~ dwSupportedBits;
//Security options
// Implementation of IObjectSafety
STDMETHODIMP CTestActiveX2Ctrl::XObjSafe::GetInterfaceSafetyOptions(
	REFIID riid, 
	DWORD __RPC_FAR *pdwSupportedOptions, 
	DWORD __RPC_FAR *pdwEnabledOptions)
{
	METHOD_PROLOGUE_EX(CTestActiveX2Ctrl, ObjSafe)

		if (!pdwSupportedOptions || !pdwEnabledOptions)
		{
			return E_POINTER;
		}

		*pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
		*pdwEnabledOptions = 0;

		if (NULL == pThis->GetInterface(&riid))
		{
			TRACE("Requested interface is not supported.\n");
			return E_NOINTERFACE;
		}

		// What interface is being checked out anyhow?
		OLECHAR szGUID[39];
		int i = StringFromGUID2(riid, szGUID, 39);

		if (riid == IID_IDispatch)
		{
			// Client wants to know if object is safe for scripting
			*pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
			return S_OK;
		}
		else if (riid == IID_IPersistPropertyBag 
			|| riid == IID_IPersistStreamInit
			|| riid == IID_IPersistStorage
			|| riid == IID_IPersistMemory)
		{
			// Those are the persistence interfaces COleWinApp derived controls support
			// as indicated in AFXCTL.H
			// Client wants to know if object is safe for initializing from persistent data
			*pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
			return S_OK;
		}
		else
		{
			// Find out what interface this is, and decide what options to enable
			TRACE("We didn't account for the safety of this interface, and it's one we support...\n");
			return E_NOINTERFACE;
		}	
}

STDMETHODIMP CTestActiveX2Ctrl::XObjSafe::SetInterfaceSafetyOptions(
	REFIID riid, 
	DWORD dwOptionSetMask, 
	DWORD dwEnabledOptions)
{
	METHOD_PROLOGUE_EX(CTestActiveX2Ctrl, ObjSafe)

		OLECHAR szGUID[39];
	// What is this interface anyway?
	// We can do a quick lookup in the registry under HKEY_CLASSES_ROOT\Interface
	int i = StringFromGUID2(riid, szGUID, 39);

	if (0 == dwOptionSetMask && 0 == dwEnabledOptions)
	{
		// the control certainly supports NO requests through the specified interface
		// so it's safe to return S_OK even if the interface isn't supported.
		return S_OK;
	}

	// Do we support the specified interface?
	if (NULL == pThis->GetInterface(&riid))
	{
		TRACE1("%s is not support.\n", szGUID);
		return E_FAIL;
	}


	if (riid == IID_IDispatch)
	{
		TRACE("Client asking if it's safe to call through IDispatch.\n");
		TRACE("In other words, is the control safe for scripting?\n");
		if (INTERFACESAFE_FOR_UNTRUSTED_CALLER == dwOptionSetMask && INTERFACESAFE_FOR_UNTRUSTED_CALLER == dwEnabledOptions)
		{
			return S_OK;
		}
		else
		{
			return E_FAIL;
		}
	}
	else if (riid == IID_IPersistPropertyBag 
		|| riid == IID_IPersistStreamInit
		|| riid == IID_IPersistStorage
		|| riid == IID_IPersistMemory)
	{
		TRACE("Client asking if it's safe to call through IPersist*.\n");
		TRACE("In other words, is the control safe for initializing from persistent data?\n");

		if (INTERFACESAFE_FOR_UNTRUSTED_DATA == dwOptionSetMask && INTERFACESAFE_FOR_UNTRUSTED_DATA == dwEnabledOptions)
		{
			return NOERROR;
		}
		else
		{
			return E_FAIL;
		}
	}
	else
	{
		TRACE1("We didn't account for the safety of %s, and it's one we support...\n", szGUID);
		return E_FAIL;
	}
}
BOOL CTestActiveX2Ctrl::CTestActiveX2CtrlFactory::UpdateRegistry(BOOL bRegister)
{
	// TODO: 컨트롤이 아파트 모델 스레딩 규칙을 준수하는지
	// 확인합니다. 자세한 내용은 MFC Technical Note 64를
	// 참조하십시오. 컨트롤이 아파트 모델 규칙에
	// 맞지 않는 경우 다음에서 여섯 번째 매개 변수를 변경합니다.
	// afxRegApartmentThreading을 0으로 설정합니다.

	if (bRegister)
		return AfxOleRegisterControlClass(
			AfxGetInstanceHandle(),
			m_clsid,
			m_lpszProgID,
			IDS_TESTACTIVEX2,
			IDB_TESTACTIVEX2,
			afxRegApartmentThreading,
			_dwTestActiveX2OleMisc,
			_tlid,
			_wVerMajor,
			_wVerMinor);
	else
		return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}



// CTestActiveX2Ctrl::CTestActiveX2Ctrl - 생성자입니다.

CTestActiveX2Ctrl::CTestActiveX2Ctrl()
{
	InitializeIIDs(&IID_DTestActiveX2, &IID_DTestActiveX2Events);
	// TODO: 여기에서 컨트롤의 인스턴스 데이터를 초기화합니다.
}



// CTestActiveX2Ctrl::~CTestActiveX2Ctrl - 소멸자입니다.

CTestActiveX2Ctrl::~CTestActiveX2Ctrl()
{
	// TODO: 여기에서 컨트롤의 인스턴스 데이터를 정리합니다.
}


void CTestActiveX2Ctrl::OnAppearanceChanged ()
{
	
}
void CTestActiveX2Ctrl::OnSetClientSite()
{
		
}
BOOL CTestActiveX2Ctrl::OnGetViewRect(DWORD dwAspect,LPRECTL pRect)
{
		

		return TRUE;
}

// CTestActiveX2Ctrl::OnDraw - 그리기 함수입니다.

void CTestActiveX2Ctrl::OnDraw(
			CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
	if (!pdc)
		return;

	// TODO: 다음 코드를 사용자가 직접 작성한 그리기 코드로 바꾸십시오.
	pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
	pdc->Ellipse(rcBounds);
}



// CTestActiveX2Ctrl::DoPropExchange - 지속성 지원입니다.

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


	AboutBox();
	AfxMessageBox(_T("DoPropExchange"));

	// TODO: 지속적인 사용자 지정 속성 모두에 대해 PX_ functions를 호출합니다.
}



// CTestActiveX2Ctrl::OnResetState - 컨트롤을 기본 상태로 다시 설정합니다.

void CTestActiveX2Ctrl::OnResetState()
{
	COleControl::OnResetState();  // DoPropExchange에 들어 있는 기본값을 다시 설정합니다.

	// TODO: 여기에서 다른 모든 컨트롤의 상태를 다시 설정합니다.
}



// CTestActiveX2Ctrl::AboutBox - "정보" 대화 상자를 사용자에게 보여 줍니다.

void CTestActiveX2Ctrl::AboutBox()
{
	CDialog dlgAbout(IDD_ABOUTBOX_TESTACTIVEX2);
	dlgAbout.DoModal();
}



// CTestActiveX2Ctrl 메시지 처리기입니다.
