(转)如何在JavaScript与ActiveX之间传递数据3
本文研究如何在JS等脚本语言与ActiveX控件之间通信,如何传递各种类型的参数,以及COM的IDispatch接口。使用类似的方法,可以推广到其他所有脚本型语言,如LUA,AutoCad等。
本文将研究以下几个方面:
1. 整形数组传参
2. 字符串参数,字符串返回值
3. 修改传入字符串内容
4. 数组参数
5. IDispatch接口介绍
6. 修改输入数组内容
7. 增加数组内容
8. 以数组传参方式,JS调用S4Execute( )
由于本文篇幅较长,所以将以连载方式进行发表,连载一主要讨论1-3点,连载二主要讨论4-6点,连载三主要讨论7-8点.
(七)增加数组内容
1. 在COM中无法向JS中一样,直接增加数组元素。只能使用属性、方法的方式访问数组对象,并以此产生增加数组元素的效果。
2. JS的Array中包含push( )、 pop( )两个方法,用于在数组尾部增减元素。在COM中需要增减元素时,可通过IDispatch:: Invoke( )接口调用 "push"、"pop"方法来实现。
3. COM中C++定义
STDMETHODIMP CJsAtl::AddNewElement(VARIANT vArray)
{
AddArrayElement(vArray.pdispVal, 123); // 增加元素,值为 123
return S_OK;
}
// ****************************************************
// 向js数组中增加元素
// ****************************************************
HRESULT AddArrayElement(IDispatch* pDisp, int value)
{
HRESULT hr = 0;
DISPID dispid[2] = {0};
CComBSTR funcName(L"push");
hr = pDisp->GetIDsOfNames(IID_NULL, &funcName, 1, LOCALE_USER_DEFAULT, dispid);
if (FAILED(hr))
return hr;
DISPID dispidNamed = DISPID_UNKNOWN;
DISPPARAMS params;
params.rgdispidNamedArgs = NULL;
params.cArgs = 1;
params.cNamedArgs = 0;
params.rgvarg = new VARIANTARG[1];
params.rgvarg[0].vt = VT_I4;
params.rgvarg[0].intVal = value;
hr = pDisp->Invoke(dispid[0], IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, ¶ms, NULL, NULL, NULL);
return hr;
}
4. JS调用
function test_add_element()
{
var array = new Array(0, 1, 2, 3);
try {
var obj = document.getElementByIdx_xx_x("obj");
obj.AddNewElement(array);
alert("length: [" + array.length + "] " + array[array.length - 1]);
} catch (e) {
alert("JS ERROR: " + e.message);
}
}
5. 测试执行
原数组:{0,1,2,3}
增加后:{0,1,2,3,123}
(八)以数组传参方式,JS调用S4Execute( )
1. 本例展示如何在JS中执行精锐4锁内程序,且以数组方式处理参数。
2. 本例在Execute传参时,直接以整形数组表示字节数组,而不再需要Hex字符串形式,使得JS端接口更加直观。
3. JS代码
var obj = document.getElementByIdx_xx_x("obj");
var deviceID = "123";
var userPin = "12345678";
var fileID = "0001";
var inBuff = new Array(1, 2, 3, 4);
var outBuff = new Array(0, 0, 0, 0);
var ret = 0;
try {
ret = obj.OpenLock(deviceID);
ret = obj.ChangeDir("\\");
ret = obj.VerifyPin(userPin);
ret = obj.Execute(fileID, inBuff, outBuff);
ret = obj.Close();
} catch (e) {
alert("JS Exception: " + e.message);
}
// JS数组操作,打印结果
var str = "";
for (var i = 0; i < outBuff.length; i++)
str += " " + outBuff[i];
alert(str);
4. ActiveX代码
SENSE4_CONTEXT g_ctx = {0}; //全局变量保存当前打开的ctx
// 打开设备,以设备ID作为筛选条件,若设备ID指定为空串,则打开第一把锁
STDMETHODIMP CS4ActiveX::OpenLock(BSTR deviceID, LONG* retVal)
{
SENSE4_CONTEXT * pctx = NULL;
unsigned long ret = 0;
unsigned long size = 0;
unsigned long devCount= 0;
unsigned long i = 0;
char bDeviceID[9] = {0};
char bUserPin[9] = {0};
S4Enum(NULL, &size);
if (size == 0)
{
*retVal = S4_NO_LIST;
goto cleanup;
}
pctx = (SENSE4_CONTEXT*) malloc(size);
ret = S4Enum(pctx, &size);
if (ret != S4_SUCCESS)
{
*retVal = ret;
goto cleanup;
}
// 获取ascii格式的设备ID
WideCharToMultiByte(CP_ACP, 0, deviceID, SysStringLen(deviceID), bDeviceID, 9, NULL, NULL);
// 遍历,寻找deviceID为指定值的设备
devCount = size / sizeof(SENSE4_CONTEXT);
for (i = 0; i < devCount; i++)
{
if (strlen(bDeviceID) == 0) // 未指定设备ID,返回第一把锁
{
break;
}
if (0 == memcmp(bDeviceID, pctx[i].bID, 8))
{
break;
}
}
// 没有找到
if (i == devCount)
{
*retVal = S4_NO_LIST;
goto cleanup;
}
memcpy(&g_ctx, &pctx[i], sizeof(SENSE4_CONTEXT));
ret = S4Open(&g_ctx);
if (ret != S4_SUCCESS)
{
*retVal = ret;
goto cleanup;
}
*retVal = S4_SUCCESS;
cleanup:
if (pctx)
{
free(pctx);
pctx = NULL;
}
return S_OK;
}
STDMETHODIMP CS4ActiveX::ChangeDir(BSTR dir, LONG* retVal)
{
char bDir[20] = {0};
WideCharToMultiByte(CP_ACP, 0, dir, SysStringLen(dir), bDir, 20, NULL, NULL);
*retVal = S4ChangeDir(&g_ctx, bDir);
return S_OK;
}
STDMETHODIMP CS4ActiveX::Execute(BSTR fileID, VARIANT inBuff, VARIANT outBuf, LONG* retVal)
{
char bFileID[5] = {0};
BYTE * bInBuff = NULL;
BYTE * bOutBuff = NULL;
int inBuffSize = 0;
int outBuffSize = 0;
unsigned long size = 0;
unsigned long ret = 0;
int i = 0;
int tmp = 0;
GetArrayLength(inBuff.pdispVal, &inBuffSize);
GetArrayLength(outBuf.pdispVal, &outBuffSize);
if (inBuffSize > 0)
bInBuff = (BYTE*) malloc(inBuffSize);
if (outBuffSize > 0)
bOutBuff = (BYTE*) malloc(outBuffSize);
for (i = 0; i < inBuffSize; i++)
{
GetArrayNumberOfIndex(inBuff.pdispVal, i, &tmp);
bInBuff[i] = (BYTE)tmp;
}
WideCharToMultiByte(CP_ACP, 0, fileID, SysStringLen(fileID), bFileID, 5, NULL, NULL);
ret = S4Execute(&g_ctx, bFileID, bInBuff, inBuffSize, bOutBuff, outBuffSize, &size);
if (ret != S4_SUCCESS)
{
*retVal = ret;
return S_FALSE;
}
for (i = 0; i < size; i++)
{
SetArrayNumberOfIndex(outBuf.pdispVal, i, bOutBuff[i]);
}
return S_OK;
}
STDMETHODIMP CS4ActiveX::VerifyPin(BSTR userPin, LONG* retVal)
{
unsigned char bUserPin[9] = {0};
WideCharToMultiByte(CP_ACP, 0, userPin, SysStringLen(userPin), (char*)bUserPin, 9, NULL, NULL);
*retVal = S4VerifyPin(&g_ctx, bUserPin, 8, S4_USER_PIN);
return S_OK;
}
STDMETHODIMP CS4ActiveX::Close(LONG* retVal)
{
*retVal = S4Close(&g_ctx);
return S_OK;
}
至此,本篇博文连载完成,希望您通过阅读此系列博文后,可以了解如何在JavaScript以及Acticex之间相互传递数据的问题,当然,也希望您与我们进行互动,能够在此基础之上,再发掘出更好的方法!!!
(转)如何在JavaScript与ActiveX之间传递数据3的更多相关文章
- (转)如何在JavaScript与ActiveX之间传递数据2
本文研究如何在JS等脚本语言与ActiveX控件之间通信,如何传递各种类型的参数,以及COM的IDispatch接口.使用类似的方法,可以推广到其他所有脚本型语言,如LUA,AutoCad等.本文将研 ...
- (转) 如何在JavaScript与ActiveX之间传递数据1
本文研究如何在JS等脚本语言与ActiveX控件之间通信,如何传递各种类型的参数,以及COM的IDispatch接口.使用类似的方法,可以推广到其他所有脚本型语言,如LUA,AutoCad等.本文将研 ...
- 【MVC架构】——怎样利用Json在View和Controller之间传递数据
在MVC架构中,尽管非常多东西和三层非常相似,可是也有非常大的差别.就比方传递数据.在三层架构中,传递数据就仅仅要一层返回,另外一层用同样类型的变量来接收即可了.在MVC中,事实上原理是一样的,Con ...
- Activity之间传递数据的方式及常见问题总结
Activity之间传递数据一般通过以下几种方式实现: 1. 通过intent传递数据 2. 通过Application 3. 使用单例 4. 静态成员变量.(可以考虑 WeakReferences) ...
- Controller之间传递数据:属性传值
在项目中,Controller之间传递数据非常之多,这里简单介绍一下属性传值.例如有FirstController 和 SecondController,数据从First传递到Second中,我们如何 ...
- Activity之间传递数据或数据包Bundle,传递对象,对象序列化,对象实现Parcelable接口
package com.gaojinhua.android.activitymsg; import android.content.Intent; import android.os.Bundle; ...
- 28、activity之间传递数据&批量传递数据
import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android ...
- 【Android 复习】 : Activity之间传递数据的几种方式
在Android开发中,我们通常需要在不同的Activity之间传递数据,下面我们就来总结一下在Activity之间数据传递的几种方式. 1. 使用Intent来传递数据 Intent表示意图,很多时 ...
- Android基础知识04—Activity活动之间传递数据
------活动之间传递数据------ 向下一个活动传递数据: Intent中提供了一系列的putExtra()方法,可以把数据暂存到Intent中,启动另一个活动的时候就可以取出来. 代码: (存 ...
随机推荐
- date 获取昨天日期
使用date -d 选项: date +"%Y%m%d" -d "+n days" 今天的后n天日期 date +" ...
- volatile,可变参数,memset,内联函数,宽字符窄字符,国际化,条件编译,预处理命令,define中##和#的区别,文件缓冲,位域
1.volatile: 要求参数修改每次都从内存中的读取.这种情况要比普通运行的变量需要的时间长. 当设置了成按照C99标准运行之后,使用volatile变量之后的程序运行的时间将比register的 ...
- android NDK 实用学习(三)- java端类对象的构造及使用
1,读此文章前我假设你已经读过: android NDK 实用学习-获取java端类及其类变量 android NDK 实用学习-java端对象成员赋值和获取对象成员值 2,java端类对象的构造: ...
- 深入prototype源码之--Class
由于工作需要项目中要用prototype框架,所以这几天捣鼓了一下,研究了一下prototype 创建对象和类以及继承的一些源码,其实早在很久以前就接触prototype,然后直接看源码, 看着太蛋疼 ...
- 【翻译】Android避免内存泄露(Activity的context 与Context.getApplicationContext)
原谅地址:http://android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html ,英文原文在翻译之后 Android 应用 ...
- ALM11用例测试类型
默认一般都是选择的是manual
- 转载 SharePoint【Site Definition 系列】– 创建Content Type
转载原地址: http://www.cnblogs.com/wsdj-ITtech/archive/2012/09/01/2470274.html Sharepoint本身就是一个丰富的大容器,里面 ...
- Countly在andoid和vps集成使用,开源的统计分析sdk
这几天项目需要,简单研究了一下countly,说实话完全满足项目需要,比umeng这类产品干净多了. Countly Mobile Analytics 下面就讲一下android 集成的过程,以及 服 ...
- MongoDB让人恶心的配置
dbpath.logpath必须指定到硬盘的根目录: dbpath=D:\data\dblogpath=D:\data\log\Mongodb.log 不然启动时会报没有设置dbpath的错误
- .NET设计模式(3):抽象工厂模式(Abstract Factory)
):抽象工厂模式(Abstract Factory) 抽象工厂模式(Abstract Factory) --探索设计模式系列之三 Terrylee,2005年12月12日 转载:http://terr ...