vc的ocx接收从vb传来的数组 我想用vc做的ocx接收从vb传来的数组..应该怎么写?vc的ocx的属性里没有数组的定义...请大家帮忙..谢谢... 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 如何在vc中定义这个数组..要定义为ocx的属性..但是classwizard中属性定义没有数组..再次感谢 定义成VARIANT,VARIANT里面能存放safearray 构造一个二维数组的SafeArray,然后把指针保存到VARIANT中就行。多了解SafeArray的使用。 safearray应该是在vb里定义,vc中只是定义一个variant准备接收既可以了对不对?? safearray应该是在vb里定义,vc中只是定义一个variant准备接收既可以了对不对??------------------------------------safearray 是 c 里面的,其他语言 vb, javascript 中的数组传递到 com 中就是safearray 。在 com 中,可以用 variant 来保存 safearray 。 to:r_swordsman:那我在vc中定义接口函数的参数的时候定义成什么类型的?你说的我有点不明白,我先把我的问题说明白,我是想从vb中传一个二维数组到vc中,这个数组在接口函数的参数里,我这个参数应该定义成什么类型呢,在vb中又该如何定义呢???还有一个问题,我把safearray里的数读到数组中,结果第一个值不对,是个很大的六位数,其余的值都正确,我读的是二维数组,为什么??? 上面已经说了啊...在 com 中,可以用 variant 来保存 safearray 。 你用 variant 类型即可 还有一个问题,我把safearray里的数读到数组中,结果第一个值不对,是个很大的六位数,其余的值都正确,我读的是二维数组,为什么???----------------是把safearray读到c++的2维数组中不?你会操作吗?看看代码 我就是读到c++的二维数组中,一下是代码: vaResult.vt = VT_ARRAY|VT_R8; vaResult.parray = psa; for(long m=0;m<4;m++) { for(long n=0;n<10;n++) { // long index = m*10+n; Demen[1]=m; Demen[0]=n; SafeArrayGetElement(vaResult.parray,Demen,zz); // SafeArrayGetElement(vaResult.parray,&index,*(zz+index)); CString ss; ss.Format("%d",zz[m][n]); MessageBox(ss); } } 8楼的不严谨:...其他语言vb,javascript中的数组传递到com中就是safearray...vb是safearray,javascript(jscript)是 IDispatchEx 8楼的不严谨: ...其他语言vb,javascript中的数组传递到com中就是safearray... vb是safearray,javascript(jscript)是 IDispatchEx ------------------------呵呵...那请问你是如果操作从javascript(jscript)传递到com中的数组呢? 呵呵...那请问你是如果操作从javascript(jscript)传递到com中的数组呢?到网上搜馊很多的,大致有两种办法:1. 直接调用 IDispatch(Ex) 的 Invoke(Ex) 方法,因为jscript的数组元素值可以看作“名字为数字的属性值”2.(代码来自网上)把javascript,vbscript中得数组传递给COM组件(or Activex) COM组件的方法在IDL中的声明:[id(1), helpstring("方法InputArray")] HRESULT InputArray([in] VARIANT vData);在脚本中建立数组并调用COM组件的方法:当数组很大的时候,like 100k ,javascript在给数组赋值的时候效率非常低!完成时间,cpu占用率,占用的内存都大的可怕。反而VBScript却完成的很好。COM组件的代码:从代码中可以看到vbscript传进来的是个SafeArray。而javascript的情况就复杂了,javascript中得数组并不是真正意义上的数组,这个“数组”传到COM中被放进一个集合里,参数VARIANT的类型被置为VT_DISPATCH,我们得通过这个IDispatch指针调用invoke才能得到用来读取集合的枚举接口。STDMETHODIMP CBigParamCtl::InputArray(VARIANT vData){ LPBYTE p ; DWORD nLen; HRESULT hr; if( vData.vt == VT_DISPATCH) { //deal with javascript array hr = VariantEnumToBytes(vData.pdispVal,&p, &nLen); } else { //deal with vbscript array hr = VariantArrayToBytes(&vData, &p, &nLen) ; } if( S_OK == hr) { //....... do sth on p delete[] p; } return S_OK;}HRESULT VariantEnumToBytes(IDispatch* disp, LPBYTE *ppBytes, DWORD *pdwBytes){ // DebugBreak(); HRESULT hr; DISPPARAMS noArgs = { NULL, NULL, 0, 0 }; CComVariant resultV; hr = disp->Invoke( DISPID_NEWENUM, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &noArgs, &resultV, NULL, NULL ); if( FAILED( hr ) && FAILED( resultV.ChangeType( VT_UNKNOWN ) ) ) return E_FAIL; // Bug 37459, above Invoke succeeds, but returns resultV.vt == VT_EMPTY, resultV->other param unchanged if (resultV.vt != VT_UNKNOWN && resultV.vt != VT_DISPATCH) { return E_FAIL; } CComQIPtr pEnum( resultV.punkVal ); if( !pEnum ) return E_FAIL; // Count the elements *pdwBytes = 0; hr = S_OK; //Get Enum Size while( hr == S_OK ) { hr = pEnum->Skip(1); if( hr == S_OK ) (*pdwBytes)++; } //allocate memory *ppBytes = (LPBYTE)new BYTE[*pdwBytes]; int nCount = 0; CComVariant elemV; pEnum->Reset(); hr = S_OK; while( hr == S_OK ) { // Could switch to use Skip when Cary gets // it working. hr = pEnum->Next( 1, &elemV, NULL ); if( elemV.vt != VT_I4 ) hr = S_FALSE; // correct for dispproxy bug 19307 else { int nTmp = elemV.lVal; (*ppBytes)[nCount] = (BYTE)nTmp; } if( hr == S_OK ) nCount++; } return S_OK;}HRESULT VariantArrayToBytes(VARIANT *pVariant, LPBYTE *ppBytes, DWORD *pdwBytes){ USES_CONVERSION; if (pVariant->vt != (VT_VARIANT | VT_BYREF)) return E_INVALIDARG; if (!(pVariant->pvarVal->vt & VT_ARRAY)) return E_INVALIDARG; SAFEARRAY* pX = NULL; if (pVariant->pvarVal->vt & VT_BYREF) pX = *(pVariant->pvarVal->pparray); else pX = pVariant->pvarVal->parray; if (::SafeArrayGetDim(pX) != 1) return E_INVALIDARG; *ppBytes = NULL; *pdwBytes = 0; VARIANT *pArray = NULL; HRESULT hr = E_FAIL; _variant_t v; hr = SafeArrayAccessData(pX, (void **) &pArray ); if( SUCCEEDED(hr)) { *pdwBytes = pX->rgsabound->cElements; *ppBytes = (LPBYTE)new BYTE[*pdwBytes]; for( DWORD i = 0; i < *pdwBytes; i++) { v = pArray[i]; v.ChangeType(VT_UI1); (*ppBytes)[i] = v.bVal; } SafeArrayUnaccessData( pX ); } else return hr; SafeArrayDestroy(pX); return S_OK;} 呵呵....我还以为javascript中的数组传递到com中不是 safearray呢看上面的代码...原来也是嘛....哈哈...safearray 就是用来在各中语言直接传递数组的. 给lz的例子,如何处理vb的数组, 注释掉的方法也可以,实现同样的功能,非线程安全:STDMETHODIMP CSimpleObjectA::put_SafeArray(VARIANT newVal){ if(newVal.vt == ::VT_ARRAY | ::VT_I4) { LPSAFEARRAY parr = newVal.parray; //if(parr->cDims == 1 && parr->rgsabound[0].cElements <= 100) //{ // memset(m_array, 0x0, 400); // ULONG l = parr->rgsabound[0].cElements; // int* p = (int*)parr->pvData; // for(ULONG i = 0; i < l; i++) // { // m_array[i] = p[i]; // } //} LONG l = 0; if(::SafeArrayGetDim(parr) == 1 && ::SafeArrayGetUBound(parr, 1, &l) == S_OK && l < 100) // 0 - 99 { memset(m_array, 0x0, 400); int v = 0; for(LONG i = 0; i < l; i++) { if(::SafeArrayGetElement(parr, &i, &v) == S_OK) m_array[i] = v; } } } return S_OK;}vb 中调用:Private Sub Command1_Click()Dim p(99) As Long ' I4, 0 - max indexp(0) = 23p(1) = 25Dim a As AltComTestA3.CSimpleObjectASet a = New AltComTestA3.CSimpleObjectAa.SafeArray = pEnd Sub vaResult.vt = VT_ARRAY ¦VT_R8; vaResult.parray = psa; for(long m=0;m <4;m++) { for(long n=0;n <10;n++) { // long index = m*10+n; Demen[1]=m; Demen[0]=n; SafeArrayGetElement(vaResult.parray,Demen,zz); <------- zz 参数不对, 你的zz应该是 c++ 的二维数组, 改为类似 &zz[m][n] // SafeArrayGetElement(vaResult.parray,&index,*(zz+index)); CString ss; ss.Format("%d",zz[m][n]); MessageBox(ss); } } 呵呵....我还以为javascript中的数组传递到com中不是 safearray呢 看上面的代码...原来也是嘛....哈哈... safearray 就是用来在各中语言直接传递数组的.楼上的,我两个都给出了,你到底看清楚了没有?! 谢谢大家..等东西弄好了一块结贴..我闲仔细看看大家的方法..我不用java.用vb传给vc做的ocx 还是不行...我觉得大家很多回答的怎么都不是我问的呢??我就是一个问题,如何把vb中的二维数组传到vc写的ocx中,用safearray和variant... CComQIPtr pEnum( resultV.punkVal );这句在VC2005下编译不过 正在学习用javascript向com传递数组参数,学习下 directshow视频采集 这个问题困扰了我2天,关于非模态对话框的释放问题,求高手解答 如何修改别人的程序啊 没源码 急急急 ie中使用ocx的问题? 界面可变问题 请问:如何清空并口缓冲区里的内容 如何给一个应用程序加前奏,并且要输入正确的用户名与口令才能启动程序 难解 CreateDIBitmap 失败 但GetLastError却返回0 关于文件保存的一个小问题 求《COM编程精彩实例》光盘源码! 想自己写个能在richedit中显示gif的控件 请问qq的ImageOle.dll 是那种com呢 就是我该怎样使用vc6的向导建这个com工程
多了解SafeArray的使用。
------------------------------------
safearray 是 c 里面的,其他语言 vb, javascript 中的数组传递到 com 中就是safearray 。
在 com 中,可以用 variant 来保存 safearray 。
----------------
是把safearray读到c++的2维数组中不?
你会操作吗?看看代码
vaResult.vt = VT_ARRAY|VT_R8;
vaResult.parray = psa;
for(long m=0;m<4;m++)
{
for(long n=0;n<10;n++)
{
// long index = m*10+n;
Demen[1]=m;
Demen[0]=n;
SafeArrayGetElement(vaResult.parray,Demen,zz);
// SafeArrayGetElement(vaResult.parray,&index,*(zz+index));
CString ss;
ss.Format("%d",zz[m][n]);
MessageBox(ss);
}
}
------------------------呵呵...那请问你是如果操作从javascript(jscript)传递到com中的数组呢?
COM组件的方法在IDL中的声明:
[id(1), helpstring("方法InputArray")] HRESULT InputArray([in] VARIANT vData);在脚本中建立数组并调用COM组件的方法:
当数组很大的时候,like 100k ,javascript在给数组赋值的时候效率非常低!完成时间,cpu占用率,
占用的内存都大的可怕。反而VBScript却完成的很好。COM组件的代码:
从代码中可以看到vbscript传进来的是个SafeArray。而javascript的情况就复杂了,javascript中得
数组并不是真正意义上的数组,这个“数组”传到COM中被放进一个集合里,参数VARIANT的类型被置
为VT_DISPATCH,我们得通过这个IDispatch指针调用invoke才能得到用来读取集合的枚举接口。STDMETHODIMP CBigParamCtl::InputArray(VARIANT vData)
{
LPBYTE p ;
DWORD nLen; HRESULT hr; if( vData.vt == VT_DISPATCH)
{
//deal with javascript array
hr = VariantEnumToBytes(vData.pdispVal,&p, &nLen);
}
else
{
//deal with vbscript array
hr = VariantArrayToBytes(&vData, &p, &nLen) ;
}
if( S_OK == hr)
{
//....... do sth on p
delete[] p;
}
return S_OK;
}HRESULT VariantEnumToBytes(IDispatch* disp, LPBYTE *ppBytes, DWORD *pdwBytes)
{
// DebugBreak();
HRESULT hr;
DISPPARAMS noArgs = { NULL, NULL, 0, 0 };
CComVariant resultV;
hr = disp->Invoke( DISPID_NEWENUM,
IID_NULL,
LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYGET,
&noArgs,
&resultV,
NULL,
NULL );
if( FAILED( hr ) && FAILED( resultV.ChangeType( VT_UNKNOWN ) ) )
return E_FAIL;
// Bug 37459, above Invoke succeeds, but returns resultV.vt == VT_EMPTY, resultV->other param unchanged
if (resultV.vt != VT_UNKNOWN && resultV.vt != VT_DISPATCH)
{
return E_FAIL;
}
CComQIPtr pEnum( resultV.punkVal );
if( !pEnum )
return E_FAIL;
// Count the elements
*pdwBytes = 0;
hr = S_OK;
//Get Enum Size
while( hr == S_OK )
{
hr = pEnum->Skip(1);
if( hr == S_OK )
(*pdwBytes)++;
}
//allocate memory
*ppBytes = (LPBYTE)new BYTE[*pdwBytes]; int nCount = 0;
CComVariant elemV;
pEnum->Reset();
hr = S_OK;
while( hr == S_OK )
{
// Could switch to use Skip when Cary gets
// it working.
hr = pEnum->Next( 1, &elemV, NULL );
if( elemV.vt != VT_I4 )
hr = S_FALSE; // correct for dispproxy bug 19307
else
{
int nTmp = elemV.lVal;
(*ppBytes)[nCount] = (BYTE)nTmp;
}
if( hr == S_OK )
nCount++;
}
return S_OK;
}HRESULT VariantArrayToBytes(VARIANT *pVariant, LPBYTE *ppBytes, DWORD *pdwBytes)
{
USES_CONVERSION;
if (pVariant->vt != (VT_VARIANT | VT_BYREF))
return E_INVALIDARG; if (!(pVariant->pvarVal->vt & VT_ARRAY))
return E_INVALIDARG; SAFEARRAY* pX = NULL;
if (pVariant->pvarVal->vt & VT_BYREF)
pX = *(pVariant->pvarVal->pparray);
else
pX = pVariant->pvarVal->parray; if (::SafeArrayGetDim(pX) != 1)
return E_INVALIDARG;
*ppBytes = NULL;
*pdwBytes = 0; VARIANT *pArray = NULL;
HRESULT hr = E_FAIL; _variant_t v;
hr = SafeArrayAccessData(pX, (void **) &pArray );
if( SUCCEEDED(hr))
{
*pdwBytes = pX->rgsabound->cElements;
*ppBytes = (LPBYTE)new BYTE[*pdwBytes]; for( DWORD i = 0; i < *pdwBytes; i++)
{
v = pArray[i];
v.ChangeType(VT_UI1);
(*ppBytes)[i] = v.bVal;
} SafeArrayUnaccessData( pX );
}
else
return hr;
SafeArrayDestroy(pX);
return S_OK;
}
{
if(newVal.vt == ::VT_ARRAY | ::VT_I4)
{
LPSAFEARRAY parr = newVal.parray; //if(parr->cDims == 1 && parr->rgsabound[0].cElements <= 100)
//{
// memset(m_array, 0x0, 400);
// ULONG l = parr->rgsabound[0].cElements;
// int* p = (int*)parr->pvData;
// for(ULONG i = 0; i < l; i++)
// {
// m_array[i] = p[i];
// }
//} LONG l = 0;
if(::SafeArrayGetDim(parr) == 1 && ::SafeArrayGetUBound(parr, 1, &l) == S_OK && l < 100) // 0 - 99
{
memset(m_array, 0x0, 400);
int v = 0;
for(LONG i = 0; i < l; i++)
{
if(::SafeArrayGetElement(parr, &i, &v) == S_OK) m_array[i] = v;
}
}
} return S_OK;
}
vb 中调用:
Private Sub Command1_Click()
Dim p(99) As Long ' I4, 0 - max indexp(0) = 23
p(1) = 25Dim a As AltComTestA3.CSimpleObjectA
Set a = New AltComTestA3.CSimpleObjectAa.SafeArray = pEnd Sub
vaResult.parray = psa; for(long m=0;m <4;m++)
{
for(long n=0;n <10;n++)
{
// long index = m*10+n;
Demen[1]=m;
Demen[0]=n;
SafeArrayGetElement(vaResult.parray,Demen,zz); <------- zz 参数不对, 你的zz应该是 c++ 的二维数组, 改为类似 &zz[m][n]
// SafeArrayGetElement(vaResult.parray,&index,*(zz+index));
CString ss;
ss.Format("%d",zz[m][n]);
MessageBox(ss);
}
}
看上面的代码...原来也是嘛....哈哈...
safearray 就是用来在各中语言直接传递数组的.楼上的,我两个都给出了,你到底看清楚了没有?!
我就是一个问题,如何把vb中的二维数组传到vc写的ocx中,用safearray和variant...
这句在VC2005下编译不过