php调用js并传入参数,Com组件调用JS代码并传递多个参数个JS函数

项目中经常碰到JS与Com组件交互的问题,通过查找网络资料和项目实际需要,总结如下:

一、Com组件简单回调JS代码

JS中定义函数

[javascript]

function printMsg(msg1, msg2, msg3, msg4, msg5) {

alert(msg1);

alert(msg2);

alert(msg3);

alert(msg4);

alert(msg5);

}

Com组件中定义函数接口,以便将JS中定义的函数作为参数传递给Com组件

头文件中定义IDispatch接口:

[cpp]

static CComPtrm_spCallback;

[cpp]

STDMETHODIMP CJSCallBack::SetJsCallbackFunc(VARIANT scriptCallback)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

// TODO: 在此添加实现代码

if (scriptCallback.vt == VT_DISPATCH)

{

m_spCallback = scriptCallback.pdispVal;

}

return S_OK;

}

在JS中调用SetJsCallbackFunc接口注册回调函数

[javascript]

var obj = new ActiveXObject("ComForJS.JSCallBack.1");

[javascript] view plaincopy

result = obj.SetJsCallbackFunc(printMsg);

Com组件中调用JS函数:

[cpp]

void CJSCallBack::CallJsFunction()

{

CComVariant avarParams[5];

avarParams[0] = “AAA”; //指定回调函数的参数

avarParams[1] = "BBB";

avarParams[2] = "CCC";

avarParams[3] = "DDD";

avarParams[4] = "EEE";

DISPPARAMS params = { avarParams, NULL, 5, 0 };

if(m_spCallback)

{

HRESULT hr = m_spCallback->Invoke(0,

IID_NULL,

LOCALE_USER_DEFAULT,

DISPATCH_METHOD,

&params, NULL, NULL, NULL);

}

}

几点注意的地方:

1,DISPPARAMS params = { avarParams, NULL, 5, 0 },中的第三个参数将决定要传递到JS函数中的参数的个数

2,在JS函数中参数的顺序与Com组件中赋值的顺序是反的,根据本例代码,参数数组中第一个是"AAA",最后一个是"EEE",但是实际在JS代码中,msg1的值是"EEE",msg5的值是"AAA"

调用过程:

[javascript]

obj.Print("AAA",0);

[cpp] view plaincopy

STDMETHODIMP CJSCallBack::Print(BSTR bstrToPrint, LONG lWait)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

CallJsFunction();

return S_OK;

}

可以发现,以上调用是单线程调用,那么,如果在Com组件中,需要多线程操作,并且要在别的线程完成一定任务之后才需要调用JS函数,而在子线程是没有办法直接调用在主线程中注册的JS函数的,又该如何处理呢?

二、Com组件中,多线程调用JS函数

针对这个问题,查阅了大量资料,基本上都是关于IDispatch接口在多线程中使用需要列集散集等概念,可能理解能力较差,最终也没能够通过这样的方式来解决实际项目中的问题,后来联想到以前项目中曾经用到过的消息窗口,于是决定尝试一番:

定义MsgWnd类:

[cpp]

class CJSCallBack;//接口类

class MsgWnd : public CWnd

{

public:

MsgWnd() {}

MsgWnd( CJSCallBack* p );

~MsgWnd() {}

protected:

afx_msg LRESULT OnRecvMsg(WPARAM wParam, LPARAM lParam);

DECLARE_MESSAGE_MAP()

private:

MsgWnd(const MsgWnd&);

MsgWnd& operator=(const MsgWnd&);

CJSCallBack* m_pParent;

};

为MsgWnd类实现构造函数以及消息处理函数,并设置MessageMap

[cpp]

#define WM_COMM WM_USER+200

BEGIN_MESSAGE_MAP(MsgWnd, CWnd)

ON_MESSAGE(WM_COMM, OnRecvMsg)

END_MESSAGE_MAP()

LRESULT MsgWnd::OnRecvMsg(WPARAM wPar, LPARAM lPar)

{

if ( NULL != m_pParent )

{

m_pParent->CallJsFunction();//调用Parent,也就是接口类中的函数

}

return 1;

}

MsgWnd::MsgWnd( CJSCallBack* p )

{

if ( NULL != p )

{

m_pParent = p;

}

}

在接口类中声明消息窗口:

[cpp]

MsgWnd* m_pMsgWnd;

[cpp]

声明线程函数:

[cpp]

static UINT CallJspFunctionThread(LPVOID param);

定义线程函数:

[cpp]

UINT CJSCallBack::CallJspFunctionThread(LPVOID param)

{

CJSCallBack* pCallBack = (CJSCallBack*)param;

while(m_bRunThread)

{

while(m_bPrint)

{

MsgWnd* pMsgWnd = pCallBack->GetMsgWnd();

if ( NULL != pMsgWnd )

{

pMsgWnd->PostMessage( WM_COMM );

}

}

sleep(20000);

}

return 0;

}

创建消息窗口并启动线程函数:

[cpp]

STDMETHODIMP CJSCallBack::Initialize(void)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

// TODO: 在此添加实现代码

if ( NULL == m_pMsgWnd )

{

m_pMsgWnd = new MsgWnd( this );

m_pMsgWnd->CreateEx(WS_EX_CLIENTEDGE,_T("Message"),

_T("Message"),WS_OVERLAPPED,0,0,0,0,HWND_MESSAGE,NULL);

}

if ( 0 == m_hThreadHandle )

{

m_hThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CallJspFunctionThread, this, 0, &m_dThreadId);

}

return S_OK;

}

线程函数启动后,将会通过pMsgWnd->PostMessage( WM_COMM ),在MsgWnd类的消息处理函数中将会调用接口类的CallJsFunction函数。

由于pMsgWnd是在主线程中创建的,因此这样一来也就相当于是在主线程中调用JS函数了,虽然不是很完美,但是也成功的解决了项目中的实际问题。

三、调用JS函数并返回值

[javascript]

function printMsg(msg1, msg2, msg3, msg4, msg5) {

alert(msg1);

alert(msg2);

alert(msg3);

alert(msg4);

alert(msg5);

return "ABCDEFG";

}

定义CComVariant变量,Invoke时用来接收来自JS函数的返回值

[cpp]

CComVariant vaResult;

HRESULT hr = m_spCallback->Invoke(0,

IID_NULL,

LOCALE_USER_DEFAULT,

DISPATCH_METHOD,

&params, &vaResult, NULL, NULL);

AfxMessageBox(vaResult.bstrVal);

执行完毕将会弹出带有字符串"ABCDEFG"的对话框

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值