本文研究如何在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_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_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之间相互传递数据的问题,当然,也希望您与我们进行互动,能够在此基础之上,再发掘出更好的方法!!!
分享到:
相关推荐
1. **C++向JavaScript传递数据**: 在C++端,我们可以使用`COleDispatchDriver`类来操作WebBrowser控件。通过调用`COleDispatchDriver::InvokeHelper`方法,可以调用WebBrowser控件的`ExecuteScript`方法执行...
在JavaScript端,你可以使用document.createElement对象创建ActiveX控件实例,然后通过控件的属性或方法传递数据。例如,如果在MFC中定义了一个名为SetData的方法,你可以在JavaScript中这样调用: ```javascript ...
- **ActiveX脚本**:这是一种用于控制ActiveX组件的技术,通常使用VBScript或JavaScript编写。它使得开发者能够动态地修改页面内容或响应用户事件。 - **VBScript**:一种轻量级的脚本语言,专为客户端和服务器端...
3. 事件驱动:通过监听控件的事件,网页可以响应控件的行为,并通过事件处理函数传递数据。 四、注意事项 1. 兼容性:ActiveX主要适用于Internet Explorer,其他现代浏览器如Chrome、Firefox并不支持。因此,需要...
1. **使用Chrome的兼容性模式**:某些版本的Chrome提供了“--enable-internal-activex”命令行开关,允许浏览器加载ActiveX控件。在启动Chrome时,可以通过在快捷方式的目标路径后添加这个开关来启用此功能。例如:...
5. **事件监听与传递**:为了实现IFRAME间的交互,你可能需要监听IFRAME外的链接点击事件,然后传递给IFRAME内,或者相反。可以使用`addEventListener`添加事件监听器,使用`dispatchEvent`或`window.postMessage`...
4. **数据通信**:可能使用JSON格式进行数据交换,因为它是Web服务和客户端之间传递数据的常见方式。 5. **前端路由**:如果项目包含多页面,可能会用到Vue Router进行页面跳转和路由管理。 6. **状态管理**:如果...
这个“前端项目-javascript-canvas-to-blob.zip”包含了一个示例项目,帮助开发者理解并应用这一功能。 该项目的核心在于`canvas.toBlob()`方法。这个方法接收一个回调函数作为参数,当转换完成时,会将生成的Blob...
在这个JS-OCR插件中,我们可以通过JavaScript在浏览器环境中实现这一功能,而无需依赖后端服务器或者第三方API。 1. OCR基础原理: OCR技术基于图像处理和模式识别。首先,图像被转换为灰度图像以增强对比度,然后...
内容概要:介绍了金格科技开发的KGChromePlugin,这是一款旨在使ActiveX控件能够在非IE浏览器上(尤其是谷歌浏览器系列)正常工作的插件。主要讲述了插件的功能特点、安装配置、接口定义及其应用场景。通过...
而ActiveX技术则是一种允许在不同应用程序之间共享组件的技术,常用于创建网页交互性控件。本篇文章将详细探讨如何使用VS2010中的MFC来创建ActiveX控件,并进一步进行打包和在WEB环境下调用。 首先,我们需要了解...
"jQuery+json异步实现JSP和struts2之间的数据传递"是一个典型的应用场景,它结合了前端JavaScript库jQuery与后端MVC框架Struts2,通过JSON这种轻量级的数据交换格式进行高效的数据交互。下面我们将详细探讨这一主题...
ActiveX控件可以嵌入到支持的宿主应用(如LabVIEW)中,使得LabVIEW程序能够直接与网页内容进行交互,例如加载URL、执行JavaScript、获取网页数据等。 标签“labview_activex labview_browser labview_web labview...
1. **JavaScript与ActiveX对象交互**: JavaScript可以通过创建ActiveXObject实例来访问和控制ActiveX控件。在本文中,我们看到了`new ActiveXObject("Excel.Application")`和`new ActiveXObject("Word.Application...
/dist # Distributables/build # Intermediate build files/src # JS source files/native # C source files for curve25519/protos # Protobuf definitions/test # Tests概述一种在同步和异步消息传递环境中工作的...
在IT领域,ActiveX与JavaScript之间的数据交换是一个重要的技术主题,尤其在开发Web应用程序时,两者间的交互可以实现丰富的客户端功能。ActiveX是Microsoft推出的一种技术,主要用于Windows平台,允许对象(如控件...
java和javascript之间的AES-ECB模式加密解密
AJAX(异步JavaScript和XML)用于在不刷新整个页面的情况下与服务器交换数据并更新部分网页内容。Fetch API是现代浏览器提供的一种替代XMLHttpRequest的新方法,更简洁易用。 9. **错误处理**: 使用`try...catch...
JavaScript利用ActiveX导出Excel,Word