The interaction between JS and Com components is often encountered in the project. The following is a summary by looking for network information and the actual needs of the project: i. Simple callback of Com components. JS code. JS defines the function [javascript] functionprintMsg (msg1, msg2, msg3, msg4, msg5) {the interaction between JS and Com components is frequently encountered in Project a. By searching for network information and the actual needs of the project, it is summarized as follows: 1. Simple callback of Com components the function [javascript] function printMsg (msg1, msg2, msg3, msg4, msg5) defined in JS Code JS {alert (msg1); alert (msg2 ); alert (msg3); alert (msg4); alert (msg5);} define the function interface in the Com component, in this way, the functions defined in JS can be passed as parameters to the Com component header file to define the IDispatch interface: [cpp] static CComPtr. M_spCallback; [cpp] STDMETHODIMP CJSCallBack: SetJsCallbackFunc (VARIANT scriptCallback) {AFX_MANAGE_STATE (AfxGetStaticModuleState (); // TODO: add the implementation code if (scriptCallback. vt = VT_DISPATCH) {m_spCallback = scriptCallback. pdispVal;} return S_ OK;} call the SetJsCallbackFunc interface in JS to register the callback function [javascript] var obj = new ActiveXObject ("ComForJS. JSCallBack.1 "); [javascript] view plaincopyresult = obj. setJsCallbac KFunc (printMsg); the Com component calls the JS function: [cpp] void CJSCallBack: CallJsFunction () {CComVariant avarParams [5]; avarParams [0] = "AAA "; // specify the callback function parameter 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) ;}} Notes: 1, DISPPARAMS params = {avarParams, NULL, 5, 0 }, the third parameter in will determine the number of parameters to be passed to the JS function 2. The order of parameters in the JS function is reversed from the order assigned in the Com component. According to the Code in this example, in the parameter array, the first is "AAA" and the last is "EEE". However, in JS Code, the value of msg1 is "EEE ", the value of msg5 is "AAA" Call process: [javascript] obj. print ("AAA", 0); [cpp] view plaincopySTDMETHODIMP CJSCallBack: Print (BSTR bstrToPrint, LONG lWait) {AFX_MANAGE_STATE (AfxGetStaticModuleState (); CallJsFunction (); return S_ OK;} can be found The preceding call is a single-threaded call. If the Com component requires multi-threaded operations, and the JS function must be called only after other threads complete a certain task, in the subthread, there is no way to directly call the JS functions registered in the main thread. What should I do? II. In the Com component, multiple threads call JS functions to solve this problem. I have consulted a lot of information about the concept of using the IDispatch interface in multiple threads such as the column distribution set, it may not be able to solve the problem in the actual project in this way. Later I thought of the message window that I used in the previous project, so I decided to try it: define MsgWnd class: [cpp] class CJSCallBack; // Interface class MsgWnd: public CWnd {public: MsgWnd () {} MsgWnd (CJSCallBack * p );~ MsgWnd () {} protected: afx_msg LRESULT OnRecvMsg (WPARAM wParam, LPARAM lParam); consume () private: MsgWnd (const MsgWnd &); MsgWnd & operator = (const MsgWnd &); CJSCallBack * m_pParent;}; implements constructors and message processing functions for the MsgWnd class, and sets 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 (); // call Parent, that is, the function} return 1;} MsgWnd: MsgWnd (CJSCallBack * p) in the interface class) {if (NULL! = P) {m_pParent = p ;}} declare the message window in the interface class: [cpp] MsgWnd * m_pMsgWnd; [cpp] declare the thread function: [cpp]
static UINT CallJspFunctionThread(LPVOID param);
Define the thread function: [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 ;}create a message window and start the thread function: [cpp] STDMETHODIMP CJSCallBack :: initialize (void) {AFX_MANAGE_STATE (AfxGetStaticModuleState (); // TODO: add the implementation code here if (NULL = m_pMsgWnd) {m_pMsgWnd = new MsgWnd (this ); m_pMsgWnd-> CreateEx (WS_EX_CLIENTEDGE, _ T ("Message"), _ T ("Message"), WS_OVERLAPPED, 0, 0, 0, HWND_MESSAGE, NULL );} if (0 = m_hThreadHandl E) {m_hThreadHandle = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) CallJspFunctionThread, this, 0, & m_dThreadId);} return S_ OK;} after the thread function is started, the callback function of the interface class is called in the message processing function of the MsgWnd class through pMsgWnd-> PostMessage (WM_COMM. Because pMsgWnd is created in the main thread, it is equivalent to calling the JS function in the main thread. Although it is not perfect, it successfully solves the actual problem in the project. 3. Call the JS function and return the value [javascript] function printMsg (msg1, msg2, msg3, msg4, msg5) {alert (msg1); alert (msg2); alert (msg3 ); alert (msg4); alert (msg5); return "ABCDEFG";} defines the CComVariant variable. When Invoke is used to receive the return value from the JS function [cpp] CComVariant vaResult; HRESULT hr = m_spCallback-> Invoke (0, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, & params, & vaResult, NULL, NULL); AfxMessageBox (vaResult. bstrVal); after the execution is complete, a dialog box with the string "ABCDEFG" will pop up.