用MFC开发ActiveX控件,如何传递自定义结构体参数呀

碼上道 2008-01-04 02:41:36
求救,用MFC开发ActiveX控件,如何传递自定义结构体参数,我要向控件里传递一个参数,可是参数列表里没有.
...全文
306 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
jameshooo 2008-01-04
  • 打赏
  • 举报
回复
最好别传递指针,除非是IUnknown或IDispatch接口指针。如果你使用的是oledb或者ado,记录集也是一个COM接口,你可以把recordset转换成IDispatch*再传递
r_swordsman 2008-01-04
  • 打赏
  • 举报
回复
如果我想传递recoordset这种参数,可以吗
----------------------------------------
可以的
碼上道 2008-01-04
  • 打赏
  • 举报
回复
如果我想传递recoordset这种参数,可以吗
碼上道 2008-01-04
  • 打赏
  • 举报
回复
感觉bstr是一种方法,有没有什么例子!
jameshooo 2008-01-04
  • 打赏
  • 举报
回复
不要使用自定义类型作为参数,如果你需要传递结构,有几种替代方式:
1、使用多个标准参数类型,对应结构中的成员;
2、使用SafeArray,把结构体按照字节方式转换成数组;
3、使用BSTR,这也是SafeArray的一种替代,因为SafeArray控制起来稍闲麻烦,而BSTR不仅仅能保存字符串,还能保存二进制数据,不用担心0的问题。
zhoujianhei 2008-01-04
  • 打赏
  • 举报
回复
http://topic.csdn.net/t/20060327/04/4641631.html
主要介绍如何开发一个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,感谢您的支持!
学习以c#的必备书 本书介绍了如何使用Visual C++ 6.0编写Windows应用程序。全书内容全面、结构清晰、由浅入深、注重实用,并结合了大量的实例,以方便读者理解。本书既包含菜单、鼠标、键盘等基本操作,又包含图形编程、Internet程序设计、数据库编程等高级主题。每章讲述一个主题,在展示知识点的同时,提供具体的演示实例,最后两章详细讲解了两个综合实例,以使读者对Visual C++编程技术有整体的认识。 目 录 第一篇 Visual C++基础 第1章 Visual C++集成开发环境 2 1.1 Visual C++的版本 2 1.2 安装Visual C++ 6.0 3 1.3 Visual C++集成开发环境 6 1.3.1 菜单栏 7 1.3.2 工具栏 11 1.3.3 工作区窗口 13 1.3.4 输出窗口 14 1.4 编写第一个程序Hello World 14 1.4.1 创建Hello World工程 15 1.4.2 编译并执行程序 16 1.5 小结 16 第2章 使用Visual C++创建基本应用程序 17 2.1 理解Visual C++工程 17 2.2 Visual C++中应用程序的类型 18 2.2.1 控制台应用程序 18 2.2.2 基于对话框的应用程序 19 2.2.3 单文档应用程序 19 2.2.4 多文档应用程序 19 2.2.5 基于HTML文档的应用程序 19 2.3 创建应用程序框架 20 2.3.1 创建基于对话框的应用程序 20 2.3.2 创建单文档应用程序 21 2.3.3 创建多文档应用程序 23 2.3.4 创建基于HTML的应用程序 24 2.4 小结 25 第3章 面向对象程序设计基础 26 3.1 面向过程与面向对象 26 3.1.1 面向过程的问题 26 3.1.2 面向对象的特性 27 3.2 C++类的基本概念 27 3.2.1 结构体与类 27 3.2.2 类与对象 29 3.2.3 类的声明、定义和实现 29 3.2.4 成员变量 31 3.2.5 成员函数 32 3.2.6 静态成员 34 3.2.7 this指针 35 3.3 构造函数 37 3.3.1 使用构造函数的原因 37 3.3.2 构造函数的使用 37 3.3.3 重载构造函数 40 3.3.4 析构函数 41 3.4 继承 43 3.4.1 继承的概念 43 3.4.2 继承的工作机制 43 3.4.3 公有继承 44 3.4.4 私有继承 46 3.4.5 保护继承 47 3.4.6 多重继承 49 3.5 异常处理 51 3.5.1 异常的概念 51 3.5.2 异常处理机制 51 3.5.3 基本异常处理方法 52 3.5.4 多个异常处理方法 54 3.6 小结 56 第4章 Visual C++调试技术 57 4.1 Debug与Release 57 4.2 调试的过程 58 4.2.1 设置断点 58 4.2.2 控制程序的运行 60 4.3 使用查看工具 60 4.3.1 弹出式调试信息泡泡 61 4.3.2 变量窗口 61 4.3.3 观察窗口 61 4.3.4 快速查看窗口 62 4.3.5 内存查看窗口 62 4.3.6 寄存器窗口 62 4.3.7 调用堆栈窗口 63 4.4 其他调试技术 63 4.4.1 TRACE宏 63 4.4.2 ASSERT宏 64 4.4.3 VERIFY宏 64 4.5 小结 64 第二篇 Windows编程 第5章 Windows程序设计 66 5.1 Windows编程简介 66 5.1.1 Windows API概述 66 5.1.2 Windows应用程序中的常用术语 69 5.2 Windows应用程序运行机制 71 5.2.1 生成Windows应用程序框架 71 5.2.2 在Windows应用程序中添加代码 71 5.2.3 编译并执行程序 74 5.3 程序入口:WinMain()函数 74 5.3.1 WinMain()函数的定义 75 5.3.2 定义和注册窗口类 76 5.3.3 创建窗口 77 5.3.4 显示和更新窗口 78 5.3.5 消息循环 78 5.4 窗口过程函数和消息处理 80 5.4.1 窗口过程函数 80 5.4.2 常用消息的处理 82 5.5 小结 84 第6章 MFC编程概述 85 6.1 MFC概述 85 6.1.1 MFC设计原理 85 6.1.2 MFC特点 86 6.1.3 MFC AppWizard向导 86 6.2 MFC层次结构设计 88 6.2.1 单文档应用程序的构成 88 6.2.2 CObject类 90 6.2.3 CCmdTarget

3,245

社区成员

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

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