如何传递自定义结构--MFC ActiveX ControlWizard建立的工程

BruceLin2008 2009-08-10 08:52:08
各位大侠们,帮帮忙,已经折腾了一个月了,找了很多资料,问了很多人,还是没有搞定,网上真的没有人能搞定??都说这里高手多,我就来了!
问题是这样的:我用MFC ActiveX ControlWizard建立了一个工程,想弄一个.OCX的控件,供其他语言调用,如JavaScript、VB、JAVA等,我需要在事件中传递一个自定义的结构数组指针,让调用者在响应到事件的地方调用该数组指针,自定义数组如下:
typedef struct YSMEMBER 
{
int nOnline; //0-离线;1-上线;
int nStatus; //0-在线;1-在线免打扰
TCHAR pszExtno[10]; // 分机号码
TCHAR pszName[20]; // 名字

}YSMEMBER, *LPYSMEMBER;

之前找了很多资料,都说是用安全数组SAFEARRAY弄成VARIANT指针进行传递,可是在VB中尝试在事件中响应调用该VARIANT指针,结构显示“变量使用了 Visual Basic 不支持的自动化类型”,在JavaScript也是没有效果。
用安全数组,小弟是这样弄的:

void CMyVariantCtrl::ExportMember()
{
YSMEMBER *pMember = NULL;
HRESULT hr;
SAFEARRAY* pSAMember = NULL;
SAFEARRAYBOUND rgbounds = {10,0};


pSAMember = SafeArrayCreate(VT_VARIANT, 1, &rgbounds);// 1为数组的维数
hr = SafeArrayAccessData(pSAMember, reinterpret_cast<PVOID*>(&pMember));

for(int i = 0; i < 10; i++){
pMember[i].nOnline = 1;
pMember[i].nStatus = 2;
_tcscpy(pMember[i].pszExtno, _T("1408"));
_tcscpy(pMember[i].pszName, _T("软件"));
}
hr = SafeArrayUnaccessData(pSAMember);

VARIANT var;
VariantInit(&var);
var.vt = VT_ARRAY|VT_UI1;
var.parray = pSAMember;
FireOnExportMember(10, &var);// 事件原型为FireOnExportMember(long nCount, VARIANT FAR* pVarMember)
VariantClear(&var);
}

网上和书中举例的都是传递简单的几个int型结构,几乎没有传递char或者TCHAR类型的元素,有的说需要在.odl文件加入数组的定义,这些没试过,有弄过ActiveX的高手们,出来帮帮忙吧。

希望大家能帮我解决这个问题,不胜感激,因为无权限发更多分的帖子,如果分数不够的话,我可以再加,高手接分吧!!
...全文
722 22 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
holly 2011-02-21
  • 打赏
  • 举报
回复
来凑个热闹。高手确实很多。
JPEXE 2009-09-27
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 iamhycljc 的回复:]
CSDN果真没人,总共在这里问了三个问题,都是没有答案
[/Quote]
这样的总结真可笑,很多人都为你给出了答案,而你就只会说"不懂COM".
蒋晟 2009-08-14
  • 打赏
  • 举报
回复
那篇文章不是有示例代码么?答案给了你都不看。太懒的人单位不会要的。
蒋晟 2009-08-14
  • 打赏
  • 举报
回复
ActiveX是基于COM,不用COM不可能
BruceLin2008 2009-08-14
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 jiangsheng 的回复:]
那篇文章不是有示例代码么?答案给了你都不看。太懒的人单位不会要的。
[/Quote]
我已经看了,而且我已经说得很明白了,不要COM的,是你的理解有问题吧?
BruceLin2008 2009-08-13
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 jiangsheng 的回复:]
建议自己写封装类
参考MFC技术文档TN065 Dual-Interface Support for OLE Automation Servers

[/Quote]
文章涉及到COM的知识,因为对COM不了解,希望能给个例子,具体的调用方法,谢谢
BruceLin2008 2009-08-13
  • 打赏
  • 举报
回复
CSDN果真没人,总共在这里问了三个问题,都是没有答案
蒋晟 2009-08-13
  • 打赏
  • 举报
回复
建议自己写封装类
参考MFC技术文档TN065 Dual-Interface Support for OLE Automation Servers
BruceLin2008 2009-08-12
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 tttyd 的回复:]
CComSafeArray仅仅是对SAFEARRAY使用的封装。
你在MFC Activex中使用SAFEARRAY就可以了。
仿照9楼写代码就是,不过不使用CComSafeArray而是使用SAFEARRAY,代码麻烦些,但应该问题不大。

SAFEARRAY类型可以供javascript之类的语言使用,对应的类型是VBArray。
[/Quote]
我自己写的那段代码不也是用SAFEARRAY对数据进行封装转化成VARINAT吗?
雪影兄弟,我实在不知道怎么弄,希望能给个具体的例子,我的邮箱iamhycljc@163.com谢谢了。
雪影 2009-08-12
  • 打赏
  • 举报
回复
CComSafeArray仅仅是对SAFEARRAY使用的封装。
你在MFC Activex中使用SAFEARRAY就可以了。
仿照9楼写代码就是,不过不使用CComSafeArray而是使用SAFEARRAY,代码麻烦些,但应该问题不大。

SAFEARRAY类型可以供javascript之类的语言使用,对应的类型是VBArray。
BruceLin2008 2009-08-12
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 oyljerry 的回复:]
4楼给的link中,我有很多相关描述和例子,多看看
http://topic.csdn.net/u/20090615/16/1201dc15-3858-4a74-ad7e-44decd26e7b7.html
[/Quote]
我已经去看了,但还是没得到满意的答案。
CComSafeArray在MFC ActiveX中好像没有,我完成程序以后是.OCX控件,window.external.GetStringList()这种调用方法,我不是很懂,我的是直接在JavaScript中:

<OBJECT id = Extend align=baseline height=0 width=0 border=0 CLASSID="CLSID:D51949BA-6BC2-47CF-95CC-43F3FD96790D" name=Extend codebase="Extend.ocx"></OBJECT>

Extend.ExportMember()// 调用方法,触发事件
oyljerry 2009-08-11
  • 打赏
  • 举报
回复
4楼给的link中,我有很多相关描述和例子,多看看
http://topic.csdn.net/u/20090615/16/1201dc15-3858-4a74-ad7e-44decd26e7b7.html
oyljerry 2009-08-11
  • 打赏
  • 举报
回复
VARIANT CMyHtmlDlgDlg::GetStringList() 
{
VARIANT varStrList;
::VariantInit(&varStrList);
CComSafeArray<BSTR> m_oArrSrInfo;
BSTR bstr1, bstr2;
bstr1 = SysAllocString(L"hello");
bstr2 = SysAllocString(L"world");
m_oArrSrInfo.Add(bstr1);
m_oArrSrInfo.Add(bstr2);
V_VT(&varStrList) = VT_VARIANT | VT_ARRAY;
V_ARRAY(&varStrList) = m_oArrSrInfo;
SysFreeString(bstr1);
SysFreeString(bstr2);
return varStrList.Detach();
}


function GetMsgList()
{
var msgList = new VBArray(window.external.GetStringList()).toArray();
}



BruceLin2008 2009-08-11
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 oyljerry 的回复:]
typedef struct YSMEMBER
{
    int    nOnline;            //0-离线;1-上线;
    int    nStatus;            //0-在线;1-在线免打扰
    TCHAR    pszExtno[10];        // 分机号码
    TCHAR    pszName[20];        // 名字

}YSMEMBER, *LPYSMEMBER;

如果需要给JS,VBScript等来调用的,你的ActiveX的接口可以定义成VARIANT类型,然后你在vc++的的代码中使用CComSafeArray,这个里面再包含你的结构体,结构体的每个元素做这个数组的成员,然后你的JavaScript中使用VBArray()来将VARIAN类型转换会js认识的array,然后一个个处理...
[/Quote]
能给出VB或者JavaScript具体的调用方法吗?谢谢了
BruceLin2008 2009-08-11
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 tttyd 的回复:]
这里有个一和你类似的问题。也是控件向其他的语言传递数组结构的问题。
http://topic.csdn.net/u/20090615/16/1201dc15-3858-4a74-ad7e-44decd26e7b7.html

通用的做法是:结构体当成一个数组,这个数组的每个元素对应结构体的每个元素,然后外面再包一层数组,等于是再加一维,类似多维数组..

在我的项目使用上述方法没问题的------向javascript传递数组
C/C++ codeSTDMETHODIMP CmyCerts::GetArray1(BSTR inCert, VARIANT* outCert)
{//m_sa在h文件中定义:CComSafeArray <VARIANT> m_sa;VariantInit(outCert);
m_sa.Add(CComVariant(_T("aaa")));
m_sa.Add(CComVariant(_T("bbb")));
m_sa.Add(CComVariant(_T("ccc")));
CComVariant var(m_sa);
var.Detach(outCert);return S_OK;
}
[/Quote]
谢谢你的分享,可以帮我下一个简单的程序吗?就是用我的结构体,写一个.OCX控件,并在JavaScript中调用的,最好是在响应事件中传递参数,希望帮助一下小弟呀,跪求!~
BruceLin2008 2009-08-11
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 bohut 的回复:]
参考一下:
在COM/DCOM中传递自定义类型(UDT)数组,方法如下: 
  1。在.idl文件中定义UDT 
  如://  定义Admin信息结构体 
          typedef   
          [   
                  uuid(02F1F404-3BD6-4fbe-9436-70250B591234),   
                  version(1.0), 
   
                  helpstring("存储管理员信息的数据结构") 
          ] 
  struct 
  { 
  INT  nAdminNo; 
  CHAR  szAdminID[MAX_ID_LEN]; 
  INT  nAdminRole; 
                                      ....... 
  }AdminInfo; 
  2。在特定接口中添加方法 
  比如:HRESULT  ReadAdminList( 
  [in]UINT  uiLen,      //  Admin列表的长度 
  [out,  retval]SAFEARRAY(AdminInfo)  *pSa); 
   
  3。更改在对象中该方法的声明和实现: 
  STDMETHOD(ReadAdminList)( 
  /*[in]*/UINT  uiLen,   
  /*[out,  retval]*/SAFEARRAY  **pSa    //  一定要进行手工更改 
  ); 
  4。实现接口功能(略) 
  5。编译,出现 
  “warning  MIDL2039  :  interface  does  not  conform  to  [oleautomation]  attribute  :  [  Parameter  'psa'  of  Procedure  ...” 
  不必理会,是编译器的bug 
  6。调用接口(略)

[/Quote]

谢谢你的回答,因为对COM不了解,整个工程是基于MFC ActiveX 做的,因此现在更需要的是在这基础上的解决方法,同样感谢你的回答!
lllsui 2009-08-11
  • 打赏
  • 举报
回复
up
雪影 2009-08-10
  • 打赏
  • 举报
回复
这里有个一和你类似的问题。也是控件向其他的语言传递数组结构的问题。
http://topic.csdn.net/u/20090615/16/1201dc15-3858-4a74-ad7e-44decd26e7b7.html

通用的做法是:结构体当成一个数组,这个数组的每个元素对应结构体的每个元素,然后外面再包一层数组,等于是再加一维,类似多维数组..

在我的项目使用上述方法没问题的------向javascript传递数组
STDMETHODIMP CmyCerts::GetArray1(BSTR inCert, VARIANT* outCert)
{
//m_sa在h文件中定义:CComSafeArray <VARIANT> m_sa;
VariantInit(outCert);
m_sa.Add(CComVariant(_T("aaa")));
m_sa.Add(CComVariant(_T("bbb")));
m_sa.Add(CComVariant(_T("ccc")));
CComVariant var(m_sa);
var.Detach(outCert);
return S_OK;
}
bluevox3000 2009-08-10
  • 打赏
  • 举报
回复
老大,你已经很真心了。我不会,帮你顶。
oyljerry 2009-08-10
  • 打赏
  • 举报
回复
typedef struct YSMEMBER
{
int nOnline; //0-离线;1-上线;
int nStatus; //0-在线;1-在线免打扰
TCHAR pszExtno[10]; // 分机号码
TCHAR pszName[20]; // 名字

}YSMEMBER, *LPYSMEMBER;

如果需要给JS,VBScript等来调用的,你的ActiveX的接口可以定义成VARIANT类型,然后你在vc++的的代码中使用CComSafeArray,这个里面再包含你的结构体,结构体的每个元素做这个数组的成员,然后你的JavaScript中使用VBArray()来将VARIAN类型转换会js认识的array,然后一个个处理...
加载更多回复(1)
主要介绍如何开发一个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,感谢您的支持!
因文件超过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,248

社区成员

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

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