zoukankan      html  css  js  c++  java
  • (转)如何在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, &params, 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之间相互传递数据的问题,当然,也希望您与我们进行互动,能够在此基础之上,再发掘出更好的方法!!!

  • 相关阅读:
    CWinApp::OnIdle 的使用方法
    C++标准模板库
    MFC日期字符串转换
    mfc 中隐藏文件的操作
    VS2010 中修改项目名称
    C# 与C++ 数组传参数区别
    C++中使用clr(通用语言库) 及相关问题
    AutoCAD 2012(64位)安装及下载地址
    0xC015000F EEFileLoadException
    Linux安装MySQL,简化的
  • 原文地址:https://www.cnblogs.com/jzxx/p/5520913.html
Copyright © 2011-2022 走看看