如何传递自定义结构--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的高手们,出来帮帮忙吧。

希望大家能帮我解决这个问题,不胜感激,因为无权限发更多分的帖子,如果分数不够的话,我可以再加,高手接分吧!!
...全文
711 22 打赏 收藏 转发到动态 举报
写回复
用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)

3,245

社区成员

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

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