www.gusucode.com > 用ActiveX重新包装了一个点对点通讯的DLL文件源码程序 > 用ActiveX重新包装了一个点对点通讯的DLL文件源码程序/P2P语音通信/VP2PCtrl.cpp

    // VP2PCtrl.cpp : CVP2PCtrl ActiveX 控件类的实现。
/*****************************************************
作者:你家的玻璃不是我砸的@vckbase.com

联系方法:xiny120@hotmail.com

BLOG:http://blog.vckbase.com/zaboli     http://www.hotlove.cn

程序简介:
    用ActiveX重新包装了一个点对点通讯的DLL文件(该DLL文件是VCKBASE上的一位前辈写的)
偶只是把它改成了一个MFC的ActiveX,这样可以方便的在VB,vbs,js等脚本语言,特别是用在IE
里面特别方便了。

    此程序主要向你说明,其实ActiveX没有多么的神秘。你遵守的它的规则,什么功能都能添加到
ActiveX中,并且和写其它的普通的程序没有什么区别!

缺点:因为同时只能有一个程序打开音频设备,所以不能开两个实例进行聊天。本来打算改改好,只
发布成品ActiveX,不发布原代码的。可最近鸟事很多,没时间。。所以连源代码都贡献了~~~
大家可以自己完善一下。如果您做了什么好的改进,请您给作者我发一份,我会十分感谢!!!


********************************************************/
#include "stdafx.h"
#include "VP2P.h"
#include "VP2PCtrl.h"
#include "VP2PPropPage.h"
#include ".\vp2pctrl.h"
#include <comcat.h>
#include "RecSocket.h"



#ifdef _DEBUG
#define new DEBUG_NEW
#endif


IMPLEMENT_DYNCREATE(CVP2PCtrl, COleControl)

BEGIN_INTERFACE_MAP(CVP2PCtrl, COleControl)
  INTERFACE_PART(CVP2PCtrl, IID_IObjectSafety, ObjectSafety)
END_INTERFACE_MAP()

// 消息映射

BEGIN_MESSAGE_MAP(CVP2PCtrl, COleControl)
	ON_OLEVERB(AFX_IDS_VERB_EDIT, OnEdit)
	ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
END_MESSAGE_MAP()



// 调度映射

BEGIN_DISPATCH_MAP(CVP2PCtrl, COleControl)
	DISP_FUNCTION_ID(CVP2PCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
	DISP_FUNCTION_ID(CVP2PCtrl, "StartTalk", dispidStartTalk, StartTalk, VT_I4, VTS_BSTR VTS_I4 VTS_I4)
	DISP_FUNCTION_ID(CVP2PCtrl, "EndTalk", dispidEndTalk, EndTalk, VT_I4, VTS_NONE)
	DISP_FUNCTION_ID(CVP2PCtrl, "GetCtrlInfo", dispidGetCtrlInfo, GetCtrlInfo, VT_I4, VTS_PI1)
	DISP_PROPERTY_EX_ID(CVP2PCtrl, "strIP", dispidstrIP, GetstrIP, SetNotSupported, VT_BSTR)
	DISP_PROPERTY_EX_ID(CVP2PCtrl, "nTcpPort", dispidnTcpPort, GetnTcpPort, SetnTcpPort, VT_I4)
	DISP_PROPERTY_EX_ID(CVP2PCtrl, "nUdpPort", dispidnUdpPort, GetnUdpPort, SetnUdpPort, VT_I4)
END_DISPATCH_MAP()



// 事件映射

BEGIN_EVENT_MAP(CVP2PCtrl, COleControl)
	EVENT_CUSTOM_ID("me_OK", eventidme_OK, me_OK, VTS_I4 VTS_I4)
END_EVENT_MAP()



// 属性页

// TODO: 按需要添加更多属性页。请记住增加计数!
BEGIN_PROPPAGEIDS(CVP2PCtrl, 1)
	PROPPAGEID(CVP2PPropPage::guid)
END_PROPPAGEIDS(CVP2PCtrl)



// 初始化类工厂和 guid

IMPLEMENT_OLECREATE_EX(CVP2PCtrl, "VP2P.VP2PCtrl.1",
	0xd3921f23, 0xa058, 0x46e1, 0x8b, 0x93, 0x3d, 0xca, 0x71, 0xb2, 0x7f, 0x3f)



// 键入库 ID 和版本

IMPLEMENT_OLETYPELIB(CVP2PCtrl, _tlid, _wVerMajor, _wVerMinor)



// 接口 ID

const IID BASED_CODE IID_DVP2P =
		{ 0x91379582, 0x7D2E, 0x49A7, { 0xA7, 0xC3, 0x1B, 0xB5, 0xDB, 0xFE, 0x9F, 0x75 } };
const IID BASED_CODE IID_DVP2PEvents =
		{ 0x8ECC6E3C, 0x2651, 0x4E38, { 0xAC, 0xD0, 0xB9, 0xD8, 0x71, 0x44, 0x59, 0x78 } };



// 控件类型信息

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

IMPLEMENT_OLECTLTYPE(CVP2PCtrl, IDS_VP2P, _dwVP2POleMisc)

// CVP2PCtrl::CVP2PCtrlFactory::UpdateRegistry -
// 添加或移除 CVP2PCtrl 的系统注册表项

BOOL CVP2PCtrl::CVP2PCtrlFactory::UpdateRegistry(BOOL bRegister)
{
	// TODO: 验证您的控件是否符合单元模型线程处理规则。
	// 有关更多信息,请参考 MFC 技术说明 64。
	// 如果您的控件不符合单元模型规则,则
	// 必须修改如下代码,将第六个参数从
	// afxRegInsertable | afxRegApartmentThreading 改为 afxRegInsertable。

	if (bRegister)
		return AfxOleRegisterControlClass(
			AfxGetInstanceHandle(),
			m_clsid,
			m_lpszProgID,
			IDS_VP2P,
			IDB_VP2P,
			afxRegInsertable | afxRegApartmentThreading,
			_dwVP2POleMisc,
			_tlid,
			_wVerMajor,
			_wVerMinor);
	else
		return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}



// CVP2PCtrl::CVP2PCtrl - 构造函数

CVP2PCtrl::CVP2PCtrl()
{
	InitializeIIDs(&IID_DVP2P, &IID_DVP2PEvents);
	// TODO: 在此初始化控件的实例数据。
	//AfxMessageBox("CVP2PCtrl::CVP2PCtrl()");
	m_talk.Ini();

}



// CVP2PCtrl::~CVP2PCtrl - 析构函数

CVP2PCtrl::~CVP2PCtrl()
{
	// TODO: 在此清理控件的实例数据。
	m_talk.End();
}


// CVP2PCtrl::OnDraw - 绘图函数

void CVP2PCtrl::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);
	CString strOut;
	CRecSocket * pRec = m_talk.GetRecSocket();
	if(pRec!=NULL)
	{
		char lpName[MAX_PATH+1];
		memset(lpName,0,sizeof(lpName));
		::GetModuleFileName(NULL,lpName,sizeof(lpName));
		strOut.Format("TCP:%d UDP:%d\r\nwww.hotlove.cn\r\n%s",m_talk.GetListenPort(),pRec->GetListenPort(),lpName);
		CFont f;
		f.CreatePointFont(90,"宋体");
		CFont * of = pdc->SelectObject(&f);
		pdc->DrawText(strOut,CRect(rcBounds),DT_CENTER);
		pdc->SelectObject(of);
	}
}



// CVP2PCtrl::DoPropExchange - 持久性支持

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

	// TODO: 为每个持久的自定义属性调用 PX_ 函数。
}



// CVP2PCtrl::OnResetState - 将控件重置为默认状态

void CVP2PCtrl::OnResetState()
{
	COleControl::OnResetState();  // 重置 DoPropExchange 中找到的默认值
	//AfxMessageBox("CVP2PCtrl::OnResetState()");

	// TODO: 在此重置任意其他控件状态。
}



// CVP2PCtrl::AboutBox - 向用户显示“关于”框

void CVP2PCtrl::AboutBox()
{
	CDialog dlgAbout(IDD_ABOUTBOX_VP2P);
	dlgAbout.DoModal();
}



// CVP2PCtrl 消息处理程序

LONG CVP2PCtrl::StartTalk(LPCTSTR bstrIP,LONG nPort,LONG nUdpPort)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	// TODO: 在此添加调度处理程序代码

	m_talk.Start(bstrIP,nPort,nUdpPort);

	return 0;
}

LONG CVP2PCtrl::EndTalk(void)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	// TODO: 在此添加调度处理程序代码
	m_talk.End();

	return 0;
}

// Implementation of IObjectSafety
STDMETHODIMP CVP2PCtrl::XObjectSafety::GetInterfaceSafetyOptions(
			REFIID riid, 
			DWORD __RPC_FAR *pdwSupportedOptions, 
			DWORD __RPC_FAR *pdwEnabledOptions)
{
	METHOD_PROLOGUE_EX(CVP2PCtrl, ObjectSafety)

	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 COleControl 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 CVP2PCtrl::XObjectSafety::SetInterfaceSafetyOptions(
		REFIID riid, 
		DWORD dwOptionSetMask, 
		DWORD dwEnabledOptions)
{
	METHOD_PROLOGUE_EX(CVP2PCtrl, ObjectSafety)

	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;
	}
}

STDMETHODIMP_(ULONG) CVP2PCtrl::XObjectSafety::AddRef()
{
	METHOD_PROLOGUE_EX_(CVP2PCtrl, ObjectSafety)
	return (ULONG)pThis->ExternalAddRef();
}

STDMETHODIMP_(ULONG) CVP2PCtrl::XObjectSafety::Release()
{
	METHOD_PROLOGUE_EX_(CVP2PCtrl, ObjectSafety)
	return (ULONG)pThis->ExternalRelease();
}

STDMETHODIMP CVP2PCtrl::XObjectSafety::QueryInterface(
	REFIID iid, LPVOID* ppvObj)
{
	METHOD_PROLOGUE_EX_(CVP2PCtrl, ObjectSafety)
	return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
}

LONG CVP2PCtrl::GetCtrlInfo(BSTR * bstrIP)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	// TODO: 在此添加调度处理程序代码
	CString strIP;
	m_talk.GetIP(strIP);
//	strIP="ddddddddddddddddddddddd";
	*bstrIP = strIP.AllocSysString();

//	*nPort=1;
//	*nUdpPort=2;
	return 0;
}

BSTR CVP2PCtrl::GetstrIP(void)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	CString strResult;

	m_talk.GetIP(strResult);
	// TODO: 在此添加调度处理程序代码

	//strResult = "127.0.0.1";
	return strResult.AllocSysString();
}

LONG CVP2PCtrl::GetnTcpPort(void)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	// TODO: 在此添加调度处理程序代码

	return m_talk.GetListenPort();

	return 0;
}

void CVP2PCtrl::SetnTcpPort(LONG newVal)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	// TODO: 在此添加属性处理程序代码

	//SetModifiedFlag();
}

LONG CVP2PCtrl::GetnUdpPort(void)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	// TODO: 在此添加调度处理程序代码
	return m_talk.GetRecSocket()->GetListenPort();
	return 0;
}

void CVP2PCtrl::SetnUdpPort(LONG newVal)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());

	// TODO: 在此添加属性处理程序代码

	//SetModifiedFlag();
}