如何把MFC做的一个程序转换成Activex控件

susu09new 2009-12-25 10:48:46
现在用MFC编了一个应用程序,想把它变成activex控件(.ocx),听说要代码移植之类的,但是不知道具体的操作,请各位兄弟伙帮帮吗!大家圣诞快乐哈。。。
...全文
254 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
susu09new 2009-12-27
  • 打赏
  • 举报
回复
非常感谢大家,问题解决了,就是把原有的函数弄过去就okay了
zealand_1 2009-12-27
  • 打赏
  • 举报
回复
原有的框架不适合了
oyljerry 2009-12-25
  • 打赏
  • 举报
回复
新建一个ATL工程,然后对应你MFC程序,建立对应的对话框,窗口,控件等,一般ATL都有对应MFC的类库
rubywang731 2009-12-25
  • 打赏
  • 举报
回复
.Add CMyDialog m_MyDialog member to your CDialogCtrl header source (don't forget to add #include "MyDialog.h")
.Using classwizard add a member function OnCreate (WM_CREATE)
int CDialogCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (COleControl::OnCreate(lpCreateStruct) == -1)
return -1;

m_MyDialog.Create(IDD_MYDIALOG, this);
return 0;
}
Modify the member function OnDraw (the dialog's size depends on the WIDTH and HEIGHT specified in the HTML file):
void CDialogCtrl::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->Ellipse(rcBounds);

m_MyDialog.MoveWindow(rcBounds, TRUE);
}
转自http://www.codeguru.com/Cpp/COM-Tech/activex/controls/article.php/c2615
sandyandy 2009-12-25
  • 打赏
  • 举报
回复
用alt新建工程, 然后再一步步移过去
  • 打赏
  • 举报
回复
http://www.vckbase.com/code/listcode.asp?mclsid=7&sclsid=702&page=3
里面有一个 【 类似画笔的绘图控件源代码】 介绍了将SDI转换为AxtiveX方法
雪影 2009-12-25
  • 打赏
  • 举报
回复
这个相当于重写所有的代码了,整个框架都得改。
虽然大部分逻辑代码可以重用,但是改写的工作量也比较大的。涉及到得知识比较多。
susu09new 2009-12-25
  • 打赏
  • 举报
回复
我想生成的activex控件,为什么要建立ATL工程?
我现在用MFC生成了一个单文档的应用程序,你的意思是让我在ATL工程中重复我程序产生的步骤是吧?但是生成的Activex工程没有view doc之类的类!如何整来?请指教。。
刚接触这块,请见谅...
主要介绍如何开发一个ActiveX控件,提供接口,与相应事件挂钩。文中涉及到VARIANT,SAFEARRAY,BSTR的详细使用方法。 另外还提供了WinSock的详细开发步骤,以及如何响应网络超时,网络断开的事件方法以及在VC,VB调用该控件的方法。 一、MFC ActiveX控件开发步骤(VC 6.0): New->Projects->MFC ActiveX ControlWizard,然后输入MFCWinSock工程名。如下图: 图一 创建工程 一路狂按Next,直至Finsh出现,再按下OK,如下图:     图二 创建完 二、架设Socket环境: 首先在StdAfx.h文件中加入下面这句代码: #include // MFC socket extensions 打开MFCWinSock.cpp文件,添加代码,看起来如下: //////////////////////////////////////////////////////////////////////////// // CMFCWinSockApp::InitInstance - DLL initialization BOOL CMFCWinSockApp::InitInstance() { BOOL bInit = COleControlModule::InitInstance(); if (bInit) { // TODO: Add your own module initialization code here. if (!AfxSocketInit()) { AfxMessageBox("无法初始化Socket,请检查!"); return FALSE; } WSADATA wsaData; WORD wVersion = MAKEWORD(1, 1);//设定为Winsock 1.1版 int errCode; errCode = WSAStartup(wVersion, &wsaData);//启动Socket服务 if (errCode) { AfxMessageBox("无法找到可以使用的 WSOCK32.DLL"); return FALSE; } } return bInit; } //////////////////////////////////////////////////////////////////////////// // CMFCWinSockApp::ExitInstance - DLL termination int CMFCWinSockApp::ExitInstance() { // TODO: Add your own module termination code here. WSACleanup();//结束网络服务 return COleControlModule::ExitInstance(); } 三,提供控件接口和事件 在MFCWinSockCtl.cpp加入如下代码: #ifndef WM_MYWINSOCK #define WM_MYWINSOCK WM_USER+1888 #endif View->ClassWizard->Automation->Add Method…如下图: 图三 创建接口 这个时候,我们为这个控件添加了一个Connect()的接口,出于通用性,安全性和扩展性的考虑,我们采用了VARIANT类型的参数, 很多人可能都不太了解该类型,又或者有接触过,但被吓怕了,那么我们来看清它的本来面目: struct tagVARIANT { union { struct __tagVARIANT { VARTYPE vt; WORD wReserved1; WORD wReserved2; WORD wReserved3; union { LONG lVal; BYTE bVal; SHORT iVal; FLOAT fltVal; DOUBLE dblVal; VARIANT_BOOL boolVal; _VARIANT_BOOL bool; SCODE scode; CY cyVal; DATE date; BSTR bstrVal; IUnknown __RPC_FAR *punkVal; IDispatch __RPC_FAR *pdispVal; SAFEARRAY __RPC_FAR *parray; BYTE __RPC_FAR *pbVal; SHORT __RPC_FAR *piVal; LONG __RPC_FAR *plVal; FLOAT __RPC_FAR *pfltVal; DOUBLE __RPC_FAR *pdblVal; VARIANT_BOOL __RPC_FAR *pboolVal; _VARIANT_BOOL __RPC_FAR *pbool; SCODE __RPC_FAR *pscode; CY __RPC_FAR *pcyVal; DATE __RPC_FAR *pdate; BSTR __RPC_FAR *pbstrVal; IUnknown __RPC_FAR *__RPC_FAR *ppunkVal; IDispatch __RPC_FAR *__RPC_FAR *ppdispVal; SAFEARRAY __RPC_FAR *__RPC_FAR *pparray; VARIANT __RPC_FAR *pvarVal; PVOID byref; CHAR cVal; USHORT uiVal; ULONG ulVal; INT intVal; UINT uintVal; DECIMAL __RPC_FAR *pdecVal; CHAR __RPC_FAR *pcVal; USHORT __RPC_FAR *puiVal; ULONG __RPC_FAR *pulVal; INT __RPC_FAR *pintVal; UINT __RPC_FAR *puintVal; struct __tagBRECORD { PVOID pvRecord; IRecordInfo __RPC_FAR *pRecInfo; } __VARIANT_NAME_4; } __VARIANT_NAME_3; } __VARIANT_NAME_2; DECIMAL decVal; } __VARIANT_NAME_1; }; 它先是一个结构体,里面有一个重要员VARTYPE vt;vt即是指明当前的数据类型,比如整型或者字符型,当指明vt后, 后面看到各种变量类型包括在一个联合体当中,也就是说指明vt后,你只能使用对应的其中之一变量类型。看着这众多的各种不同 类型变量集中在一起,确实让人吓了一跳,但细细看来,大多数变量跟我们平时的用法相似。值得一提的是SAFEARRAY __RPC_FAR *parray; 也许有很多人还没有接触过SAFEARRAY类型的变量,SAFEARRAY实际上也是一个结构,大家可以参考MSDN,我也将在后面介绍它的具体使用方法。 用同样的方法创建DisConnect()接口 创建两个事件,FireCloseWinsock()响应网络断开事件,FireRecvSockEvent()响应网络有数据到达的事件。创建方法如下图: 图四 创建事件 重载控件消息处理函数WindowProc(),在View->ClassWizard中打开类向导,在消息映射中找到WindowProc,如下图: 图五 重载WindowProc() 四、编写代码 编写VariantToLong()转换函数,该函数代码如下: //类型转换,将VARIANT类型转换Long类型 long CMFCWinSockCtrl::VariantToLong(const VARIANT &var) { long r; switch(var.vt) { case VT_UI2://USHORT r = var.uiVal; break; case VT_UI4://ULONG r = var.ulVal; break; case VT_INT://INT r = var.intVal; break; case VT_UINT://UINT r = var.uintVal; break; case VT_I4://LONG r = var.lVal; break; case VT_UI1://BYTE r = var.bVal; break; case VT_I2://SHORT r = var.iVal; break; case VT_R4://FLOAT r = (long)var.fltVal; break; case VT_R8://DOUBLE r = (long)var.dblVal; break; default: r = -1;//无法转换该值 break; } return r; } 大家可以看到,该函数将最基本的若干中数据类型转换了long类型,但VARIANT决不是个简单的谱,我将在后面继续揭开它的神秘面纱. 编写我们刚才的接口Connect(),代码代码如下: 在MFCWinSockCtrl.h中加入 SOCKET OnlySock;//建立的唯一Socket,不允许重复建立多个 bool isOnlyConnect;//是否建立了连接 然后再编写Connect(),看起来如下: BOOL CMFCWinSockCtrl::Connect(const VARIANT FAR& RemoteHost, const VARIANT FAR& RemotePort) { // TODO: Add your dispatch handler code here if(isOnlyConnect)//该连接已建立,还没有断开 return FALSE; CString IPAddress; int Port;//转换整型的端口 switch(RemoteHost.vt) { case VT_BSTR://字符串型 IPAddress = CString(RemoteHost.bstrVal); break; case VT_BYREF|VT_I1://CHAR * IPAddress.Format("%s",RemoteHost.pcVal);//RemoteHost.pbstrVal); break; default: IPAddress = ""; return FALSE; } Port = VariantToLong(RemotePort);//我们编写的一个VARIANT转换long类型的函数 if(Port<=0) return FALSE; _TCHAR *ip = 0; struct hostent *host = 0; struct sockaddr_in addr; ULONG dotIP = inet_addr(IPAddress); OnlySock = socket(AF_INET, SOCK_STREAM, 0); // 判断是否为点IP地址格式 if (OnlySock == INVALID_SOCKET) { shutdown(OnlySock, 0x02); closesocket(OnlySock);//释放占有的SOCK资源 return FALSE; } memset(&addr, 0, sizeof(struct sockaddr_in)); // 设定 SOCKADDR_IN 结构的内容 // 如果通讯协议是选择IP Protocol,那此值固定为AF_INET // AF_INET 与 PF_INET 这两个常量值相同 addr.sin_family = AF_INET; addr.sin_port = htons(Port); addr.sin_addr.S_un.S_addr = dotIP; if (dotIP == INADDR_NONE) { host = gethostbyname(IPAddress); if (!host) { shutdown(OnlySock, 0x02); closesocket(OnlySock);//释放占有的SOCK资源 return FALSE; }; ip = inet_ntoa(*(struct in_addr*)(*host->h_addr_list)); addr.sin_addr.S_un.S_addr = inet_addr(ip); } //开始连线 if (connect(OnlySock, (LPSOCKADDR)&addr, sizeof(SOCKADDR))) { shutdown(OnlySock, 0x02); closesocket(OnlySock);//释放占有的SOCK资源 return FALSE; } int iError = WSAAsyncSelect(OnlySock, m_hWnd,WM_MYWINSOCK, FD_READ|FD_CLOSE); //只对网络断开和数据到达通知感兴趣 if(iError == SOCKET_ERROR)//无法绑定Winsock的事件通知 { shutdown(OnlySock, 0x02); closesocket(OnlySock);//释放占有的SOCK资源 return FALSE; } isOnlyConnect = true; return TRUE; } 有必要提一下WSAAsyncSelect(),这里接收网络数据到达和断开的两个消息,我们收到WM_MYWINSOCK消息时将处理该消息并作为事件传送给调用者. 第二个参数,窗口句柄,我们传送了m_hWnd,这是因为MFC ActiveX也属于一个窗口,并且是可见的,因此可以功。 编写WindowProc(),代码看起来如下: LRESULT CMFCWinSockCtrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { // TODO: Add your specialized code here and/or call the base class switch(message) { case WM_MYWINSOCK://响应自定义的消息 switch(WSAGETSELECTEVENT(lParam)) { case FD_READ://有新数据到达 FireRecvSockEvent(); break; case FD_CLOSE://对方已断掉当前连接 FireCloseWinsock(); break; } break; default: break; } return COleControl::WindowProc(message, wParam, lParam); } 本部分结束语: 好了,现在一个可以运行的控件已经完,里面提供有Connect()和DisConnect()接口,和RecvSockEvent()及CloseWinsock()事件。以及WinSock的使用方法。 在下一部分(高级篇)将讲解两个重要接口SendData()和GetData(),下期内容如下: long SendData(const VARIANT FAR& Data, const VARIANT FAR& DataType,const VARIANT FAR& DataLength, const VARIANT FAR& TimeOut) long GetData(VARIANT FAR* Data, const VARIANT FAR& DataType, const VARIANT FAR& DataMaxLength, const VARIANT FAR& TimeOut) VARIANT和SAFEARRAY的复杂用法。 控件开发出来后在VC和VB环境下的使用方法。 声明: 部分资料来源于网络,本文所用的所有源代码仅供非商业用途,并请保留原版权,否则后果自负! 欢迎大家拍砖,或指正不足的地方,一起探导更好的方法。 欢迎访问www.59186618.com,感谢您的支持!
主要利用VARIANT类型作参数进行的网络数据传送和接收,以及SAFEARRAY,BSTR的详细使用方法。 另外还提供该控件在VC,VB下的调用方式以及相关数据的处理。 关键字:ActiveX,Socket,VARIANT, SAFEARRAY,BSTR。 回顾:在上一篇文章《标准MFC WinSock ActiveX控件开发实例》中我们详细介绍了控件的开发过程,以及接口和事件的 添加和响应方法。现在我们将继续上次没有写完的控件继续进行开发,并完善作为一个WinSock控件应该具备的功能。 二、按照前一篇文章提到的知识,现在我们来添加两个新的接口分别是SendData()和GetData(),它们看起来如下: //网络数据发送,在指定的超时时间内进行发送然后返回,功返回实际发送字节数,否则返回负数 long CMFCWinSockCtrl::SendData(const VARIANT FAR& Data, const VARIANT FAR& DataType, const VARIANT FAR& DataLength, const VARIANT FAR& TimeOut) { // TODO: Add your dispatch handler code here return 0; } //获取数据,并指定获取数据的超时时间,返回实际获取到的数据长度,否则返回负数 long CMFCWinSockCtrl::GetData(VARIANT FAR* Data, const VARIANT FAR& DataType, const VARIANT FAR& DataMaxLength, const VARIANT FAR& TimeOut) { // TODO: Add your dispatch handler code here return 0; }   两个接口的参数除了第一个参数外,其它都类似。SendData()是发送数据,不要求将数据带回,因此直接用 VARIANT,而GetData()则要求将数据带回来给调用者,因此定义为 VARIANT *类型,第二个参数DataType故名思义是定义所传送或接收数据的类型,第三个参数是传送或接收数据的长度,这里的长度以char作为一个长度,假如传入的类型是int类型,则长度为4,如果定义的是字符串,一个中文字符占用2个长度。最后一个参数,是网络发送或读取时的超时时间。 三、为Connect()接口添加源代码,看起来如下: //网络数据发送,在指定的超时时间内进行发送然后返回,功返回实际发送字节数,否则返回负数 long CMFCWinSockCtrl::SendData(const VARIANT FAR& Data, const VARIANT FAR& DataType, const VARIANT FAR& DataLength, const VARIANT FAR& TimeOut) { // TODO: Add your dispatch handler code here if(!OnlySock) return -1;//网络尚未开始建立连接 int gDataType = VariantToLong(DataType); long gDataLength = VariantToLong(DataLength); int gTimeOut = VariantToLong(TimeOut); if(gDataType < 0) return -2; if(gDataLength <= 0) return -2; if(gTimeOut < 0) return -2; switch(gDataType) { case 0://默认形式,这时如果发现Data为整型数组,将不进行任何转换,直接把一个int传给一个char传送(数据可能溢出范围) case 1://当指定该值为1时,当Date为长整型数组时,将把一个long转换四个char传送 case 2://当指定该值为2时,当Date为整型数组时,将把一个int转换四个char传送 case 3://当指定该值为3时,当Date为无符号短整型数组时,将把一个unsigned short转换两个char传送 case 4://当指定该值为4时,当Date为BYTE数组时,将把一个BYTE转换一个char传送 case 5://当指定该值为5时,当Date为短整型数组时,将把一个short转换两个char传送 case 6://当指定该值为6时,当Date为浮点型数组时,将把一个float转换四个char传送 case 7://当指定该值为7时,当Date为双精度数组时,将把一个double转换八个char传送 break; default://如果不在上面取值范围内,将按当前的Data相应类型进行传送 break; } timeval tv; fd_set fdwrite; int len = 0; long m = 0; long n = 0; long changetype = 0;//将浮点型数据进行类型转换,再进行传送 VARIANT gData; VariantInit(&gData); //送出信息至服务器 FD_ZERO(&fdwrite); tv.tv_sec = gTimeOut;//指定时间后返回 tv.tv_usec = 0; FD_SET(OnlySock,&fdwrite);//是否可以发送数据 select(0,NULL,&fdwrite,NULL,&tv); char *buffer = NULL; if(FD_ISSET(OnlySock,&fdwrite)) { switch(Data.vt) { case VT_BSTR://按字符串形式发送 buffer = _com_util::ConvertBSTRToString(Data.bstrVal); break; case VT_BYREF|VT_UI1: //按BYTE*形式发送 buffer = new char[gDataLength]; memcpy(buffer,Data.pbVal,gDataLength); break; case VT_BYREF|VT_I1://按 char * 发送 buffer = new char[gDataLength]; memcpy(buffer,Data.pcVal,gDataLength); break; case VT_ARRAY|VT_I4://以长整型数组发送 gData.vt = VT_I4; if(gDataType!=0)//long = char*4 { //sizeof(long),在这里一个长整型的长度为4个char buffer = new char[gDataLength]; for(m=0,n=0; n>24)&0xff; buffer[m++] = (gData.lVal>>16)&0xff; buffer[m++] = (gData.lVal>>8)&0xff; buffer[m++] = gData.lVal&0xff; } } else//long = char*1 //数据可能溢出 { buffer = new char[gDataLength]; for(m=0,n=0; n一个int等于四个char buffer = new char[gDataLength]; for(m=0,n=0; n>24)&0xff; buffer[m++] = (gData.intVal>>16)&0xff; buffer[m++] = (gData.intVal>>8)&0xff; buffer[m++] = gData.intVal&0xff; } } else { buffer = new char[gDataLength]; for(n=0; n一个char等于一个BYTE不必进行转换 buffer = new char[gDataLength]; for(n=0; n24)&0xff; buffer[1] = (lData>>16)&0xff; buffer[2] = (lData>>8)&0xff; buffer[3] = lData&0xff; //4个char组一个long lData_2 = ((buffer[0]&0xff)<<24) + ((buffer[1]&0xff)<<16) + ((buffer[2]&0xff)<<8) + (buffer[3]&0xff); 四、现在来看看GetData()的处理,具体实现,请看如下代码: // TODO: Add your dispatch handler code here if(!OnlySock) return -1;//网络尚未开始建立连接 int gDataType = VariantToLong(DataType); long gDataMaxLength = VariantToLong(DataMaxLength); int gTimeOut = VariantToLong(TimeOut); if(gDataType < 0) return -2; if(gDataMaxLength <= 0) return -2; if(gTimeOut < 0) return -2; switch(gDataType) { case 0://默认形式,这时如果发现Data为整型数组,将不进行任何转换,直接把一个int传给一个char传送(数据可能溢出范围) case 1://当指定该值为1时,当Date为长整型数组时,将把一个long转换四个char传送 case 2://当指定该值为2时,当Date为整型数组时,将把一个int转换四个char传送 case 3://当指定该值为3时,当Date为无符号短整型数组时,将把一个unsigned short转换两个char传送 case 4://当指定该值为4时,当Date为BYTE数组时,将把一个BYTE转换一个char传送 case 5://当指定该值为5时,当Date为短整型数组时,将把一个short转换两个char传送 case 6://当指定该值为6时,当Date为浮点型数组时,将把一个float转换四个char传送 case 7://当指定该值为7时,当Date为双精度数组时,将把一个double转换八个char传送 break; default://如果不在上面取值范围内,将按当前的Data相应类型进行传送 break; } timeval tv; fd_set fdread; int len = -3;//如果找不到该连接,则返回-3 long n = 0; long m = 0; long changetype = 0; VARIANT gData; VariantInit(&gData); char *buffer=NULL; buffer = new char[gDataMaxLength+1]; memset(buffer, 0, gDataMaxLength+1); FD_ZERO(&fdread); tv.tv_sec = gTimeOut;//超过指定时间后返回 tv.tv_usec = 0; FD_SET(OnlySock,&fdread);//是否可以读取数据 select( 0,&fdread,NULL,NULL,&tv); if(FD_ISSET(OnlySock,&fdread)) { len = recv(OnlySock, buffer, gDataMaxLength, 0); if (len<=0) { delete[] buffer; return -102;//无法读取数据,对方可能已断开连接 } if(lenvt) { case VT_BSTR://按字符串形式接收 buffer[gDataMaxLength] = '\0'; Data->bstrVal = _com_util::ConvertStringToBSTR(buffer); break; case VT_BYREF|VT_UI1: //按BYTE*形式接收 memcpy(Data->pbVal,buffer,gDataMaxLength); break; case VT_BYREF|VT_I1://按 char * 形式接收 memcpy(Data->pcVal,buffer,gDataMaxLength); break; case VT_BYREF|VT_I4://以长整型指针接收 buffer[gDataMaxLength]='\0'; for(n=0; nplVal[n] = buffer[n]; } break; case VT_ARRAY|VT_I4://以长整型数组接收 gData.vt = VT_I4; if(gDataType != 0) { for(m=0,n=0; n控件: VC调用控件方式: 新建一对话框工程,然后在工程中添加该控件,设置如下图: 图一 创建新对话框工程,并加入控件 响应控件的断网和数据到达事件,设置如下图: 图二 响应控件的两个事件 添加相应代码,看起来如下: void CTestMFCWinSockDlg::OnRecvSockEventMfcwinsockctrl1() { // TODO: Add your control notification handler code here SAFEARRAYBOUND Bound[1];//一维数组 Bound[0].lLbound=0; Bound[0].cElements=100;//该一维数组最大接收100个元素 VARIANT *data; data = new VARIANT; VariantInit(data); data->vt = VT_ARRAY|VT_I4;//指明为长整型数组 data->parray = SafeArrayCreate(VT_I4,1,Bound);//创建SAFEARRAY结构 long l = m_sock.GetData(data, COleVariant((long)0), COleVariant((long)100), COleVariant((long)3)); if(l<=0) { ;//在这里判断出错信息,并作相应处理,我就偷懒了. } char pData[100]={0};//这里以字符数组显示结果 long change = 0; for(long n=0; nparray,&n,&change); pData[n] = (char)change; } CString mess; mess.Format("%s",pData); AfxMessageBox(mess); SafeArrayDestroy(data->parray); delete data; } void CTestMFCWinSockDlg::OnCloseWinsockMfcwinsockctrl1() { // TODO: Add your control notification handler code here m_sock.DisConnect();//调用断开连接接口 AfxMessageBox("服务器断开了该次连接,请检查!"); } void CTestMFCWinSockDlg::OnConnect() { // TODO: Add your control notification handler code here UpdateData(TRUE); if(!m_sock.Connect(COleVariant(m_ip),COleVariant(m_port))) AfxMessageBox("与服务器建立连接失败,请确认服务器是否存在!"); } VB调用控件方式: VB时面调用要方便很多,这得益于VB的很多自动化功能,请看下图: 图三 VB调用控件方法 同样,双击我们的控件,然后添加控件事件,如下图: 图四 VB响应控件事件 然后,添加相关代码如下: Private Sub Command1_Click() MFCWinSock1.Connect CStr(ip), CLng(port) End Sub Private Sub Command2_Click() MFCWinSock1.SendData "SendData: 欢迎使用!", 0, 50, 3 End Sub Private Sub MFCWinSock1_CloseWinsock() MFCWinSock1.DisConnect MsgBox "服务器断开了连接,请检查!" End Sub Private Sub MFCWinSock1_RecvSockEvent() Dim data As Variant Dim data2(100) As Long Dim data3 As String Dim l As Long data = data2 '在VB里当把一个Variant变量data等于另一个确定变量data2时,data将被初始化为与data2相同的类型变量 'data = data3 '如果让data等于data3,那么data将变字符串型的变量参数 l = MFCWinSock1.GetData(data, 0, 100, 3) '这时data里面已存放了接收到的数据 data3 = data(0) '这里只显示接收到的首字符编码 MsgBox data3 End Sub 大家可以看到,对于SAFEARRAY类型的数据进行相关处理也并不可怕,由于在源码里给出了具体代码和详细注解,在这里我就不再赘述了, 至于BSTR和char *类型的数据,相信不用我多说,大家也已经知道如何使用了。 结束语:   全文至此暂告一段落,本文向大家展示了MFC ActiveX控件的魅力,以及所用的VARIANT类型参数,还详细给出了WinSock的开发代码, 以用在VC,VB的调用方法,由于这段时间忙于一些新项目的开发,因此没办法花太多时间进行详细解释,所以很多地方都直接给出源代码 再加上注解,而没有进行通俗的讲解,还请各位读者仔细查看源代码。 本控件目前只能作为客户端,阁下还可以继续进行完善,比如进行端口的监听,实现服务器的相关处理等等,但这已经不是本文的目的, 授人以鱼,不如授人如渔,剩下的功能,就由各位读者去实现了,也欢迎与我进行交流,谢谢! 另外:本文的示例,需要一个服务器程序,大家可以在网上随便下载一下进行测试,我就不提供了。 声明: 部分资料来源于网络,本文所用的所有源代码仅供非商业用途,并请保留原版权,否则后果自负! 欢迎大家拍砖,指正错误或不足的地方,一起探导更好的方法。 欢迎访问www.59186618.com,感谢您的支持!
因文件超过20M不能上传,所以拆分为两个文件分次上传 第1章 COM背景知识 1.1 COM的起源 1.1.1 软件业面临的挑战 1.1.2 传统解决方案 1.1.3 面向对象程序设计方法 1.1.4 最终解决方案:组件软件 1.1.5 面向对象的组件模型——COM 1.2 COM的发展历程 1.2.1 COM以前的对象技术:DDE、OLE 1、VBX控件 1.2.2 COM首次亮相:OLE2 1.2.3 Microsoft拥抱Internet:ActiveX 1.2.4 更多的新名词:Windows DNA和COM+ 1.2.5 远程对象:ORBs和DCOM 1.2.6 COM的最新版本:COM+ 1.3 COM技术现状 1.3.1 COM与CORBA 1.3.2 COM与Enterprise Java Beans 1.3.3 Windows之外的COM 小结 第2章 从C++到COM 2.1 C++客户重用C++对象——例程DB 2.1.1 C++对象 2.1.2 客户程序 2.2 将C++对象移进DLL中——例程DB_cppdll 2.2.1 员函数的引出 2.2.2 内存分配 2.2.3 Unicode/ASCII兼容 2.2.4 例程实现 2.2.4.1 修改接口文件 2.2.4.2 修改对象程序 2.2.4.3 修改客户程序 2.3 C++对象使用抽象基类——例程DB_vtbl 2.3.1 问题:私有数据员被暴露 2.3.2 解决方案:抽象基类 2.3.2.1 什么是抽象基类(Abstract Base Class) 2.3.2.2 实现秘诀:虚函数(Virtual Functions) 2.3.3 使用抽象基类 2.3.4 例程实现 2.3.4.1 修改接口文件 2.3.4.2 修改对象程序 2.3.4.3 修改客户程序 2.4 改由COM库装载C++对象——例程dbalmostcom 2.4.1 COM库 2.4.2 对象创建的标准入口点 2.4.3 标准对象创建API 2.4.4 标准对象注册 2.4.5 例程实现 2.4.5.1 修改接口文件 2.4.5.2 修改对象程序 2.4.5.3 修改客户程序 2.5 将C++对象变COM对象 2.5.1 引用计数 2.5.2 多接口 2.5.3 IUnknown接口 2.5.4 标准类厂接口:IClassFactory 2.5.5 对象代码的动态卸载 2.5.6 自动注册 2.5.7 例程实现 2.5.7.1 修改接口文件 2.5.7.2 修改对象程序 2.5.7.3 修改客户程序 2.6 为COM对象添加多接口支持 2.6.1 多接口 2.6.2 DEFINE_GUID 2.6.3 例程实现 2.6.3.1 修改接口文件 2.6.3.2 修改对象程序 2.6.3.3 修改客户程序 小结 第3章 COM基础知识 3.1 对象与接口 3.1.1 COM对象 3.1.2 COM接口 3.1.3 IUnknown接口 3.1.3.1 生存期控制:AddRef和Release 3.1.3.2 接口查询:QueryInterface 3.1.4 全球唯一标识符GUID 3.1.5 COM接口定义 3.1.6 接口描述语言IDL 3.2 COM应用模型 3.2.1 客户/服务器模型 3.2.2 进程内组件 3.2.3 进程外组件 3.2.4 COM库 3.2.5 HRESULT返回值 3.2.6 COM与注册表 3.3 COM组件 3.3.1 实现类厂对象 3.3.2 类厂对象的创建 3.3.3 实现自动注册 3.3.4 实现自动卸载 3.4 COM客户 3.4.1 COM对象创建函数 3.4.1.1 CoGetClassObject 3.4.1.2 CoCreateInstance 3.4.1.3 CoCreateInstanceEx 3.4.2 如何调用进程内组件 3.4.3 COM客户调用进程外组件 3.5 进一步认识COM 3.5.1 可重用机制:包容和聚合 3.5.2 进程透明性 3.5.3 安全性机制 小结 第4章 COM扩展技术 4.1 可连接对象机制 4.1.1 客户、接收器与可连接对象 4.1.1.1 接收器 4.1.1.2 可连接对象 4.1.1.3 客户 4.1.2 实现可连接对象 4.1.3 实现接收器 4.1.4 建立接收器与连接点的连接 4.1.5 获得出接口的类型信息 4.2 结构化存储 4.2.1 什么叫结构化存储和复合文件 4.2.2 存储对象和IStorage接口 4.2.2.1 IStorage接口 4.2.2.2 获得IStorage指针 4.2.2.3 释放STATSTG内存 4.2.2.4 枚举存储对象中的元

3,245

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧