现在的位置: 首页 > 综合 > 正文

CallJs

2013年10月15日 ⁄ 综合 ⁄ 共 6686字 ⁄ 字号 评论关闭

C++ call JavaScript,介绍2种解决方案:1种嵌Webkit作浏览器(纯QT方法);另1种嵌IE控件作为浏览器(适用于非QT,但我是在QT里使用的)。

 

 

 

    这个需求比较冷门,所以资料少,搞起来比较折腾人。

 

 

 

    解放方案1:使用Webkit library (可以说是纯QT实现)

 

 

 

    代码量不多,直接贴代码 (读起来一点不痛苦的) :

 

 

 

    myWebView = new QWebView(this); //this 是main window widget, myWebView 是它的成员变量

 

 

 

    myWebView->page()->settings()->setAttribute(QWebSettings::JavascriptEnabled, true);

 

 

 

    myWebView->page()->settings()->setAttribute(QWebSettings::PluginsEnabled,true)

 

 

 

    myWebView->page()->mainFrame()->addToJavaScriptWindowObject("mainWindowObject", this);  //html页面中,可以通过"mainWindowObject"这个对象名访问主控件中的方法 (slot)

 

 

 

    setCentralWidget(myWebView);

 

 

 

    myWebView->setUrl( xxx ); //xxx是你的url或本地html路径

 

 

 

    //. . .

 

 

 

    class MainWindow : public QMainWindow

 

 

 

    {

 

 

 

    //. . .

 

 

 

    public slots:

 

 

 

    void CPlusPlusFunction(const QString& str) //这个函数是将被JavaScript调用的

 

 

 

    {

 

 

 

    myWebView->page()->mainFrame()->uateJavaScript( QObject::tr("jsFunction('Popup Dialog')") );

 

 

 

    }

 

 

 

    };

 

 

 

    HTML文件内容如下:

 

 

 

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

 

 

 

    <html xmlns="http://www.w3.org/1999/xhtml">

 

 

 

    <head>

 

 

 

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

 

 

 

    <title>myjstest</title>

 

 

 

    <script language="JavaScript" type="text/javascript">

 

 

 

    function jsFunction(values) //this function will be called from C++ codes

 

 

 

    {

 

 

 

    alert(values);

 

 

 

    }

 

 

 

    function test()

 

 

 

    {

 

 

 

    mainWindowObject.CPlusPlusFunction( "calling C++ function from javaScript" );

 

 

 

    }

 

 

 

    </script>

 

 

 

    </head>

 

 

 

    <body>

 

 

 

    <div id="dest"></div><form action="" method="post">

 

 

 

    <input type="button" name="" value="myTest" onclick="test()" />

 

 

 

    </form>

 

 

 

    </body>

 

 

 

    </html>

 

 

 

    这种方法,使用Webkit作为浏览器,如果你的页面使用了ActiveX控件(比如google earth插件),则不能正常工作。

 

 

 

    这种情况下,你需要放弃Webkit,在主程序中调用IE 控件(WebBrowser Control)作为浏览器。(但是这样也失去了跨平台的支持,因为IE只能在Wndosw上跑。)

 

 

 

    这就是下面要介绍的解决方案2。

 

 

 

 

 

 

 

    解决方案2:使用IE控件作为浏览器

 

 

 

    myWebBrowser = new QAxWidget(this); //this 是main window widget, myWebBrowser 是它的成员变量

 

 

 

    myWebBrowser->setControl(QString::fromUtf8("{8856F961-340A-11D0-A96B-00C04FD705A2}")); //设置IE控件

 

 

 

    myWebBrowser->setObjectName(QString::fromUtf8("WebBrowser"));

 

 

 

    myWebBrowser->setFocusPolicy(Qt::StrongFocus);

 

 

 

    setCentralWidget(myWebBrowser);

 

 

 

    myWebBrowser->dynamicCall("Navigate(const QString&)", xxx);  //打开一个页面,xxx是你的url或本地html路径

 

 

 

    //. . . 等页面加载好后,使用C++代码调用JS代码

 

 

 

    IWebBrowser2 *webBrowser = 0;

 

 

 

    myWebBrowser->queryInterface(IID_IWebBrowser2, (void **)&webBrowser);

 

 

 

    if (webBrowser) {

 

 

 

    CComPtr<IDispatch> spDisp = NULL;

 

 

 

    webBrowser->get_Document(&spDisp);

 

 

 

    myWebPage.SetDocument(spDisp); //注意,myWebPage的类型是CWebPage,关于它的定义,稍后有介绍

 

 

 

    myWebPage.CallJScript("f2", "abc"); //调用页面中的f2函数,它有一个参数,这里填“abc”

 

 

 

    webBrowser->Release();

 

 

 

    }

 

 

 

    //. . . CWebPage类的定义(粘贴的代码有点长,但是其实读起来很简单的)

 

 

 

    头文件(代码片段):

 

 

 

    class CWebPage

 

 

 

    {

 

 

 

    public:

 

 

 

    CWebPage();

 

 

 

    virtual ~CWebPage();

 

 

 

    bool SetDocument(IDispatch* pDisp);

 

 

 

    LPDISPATCH GetHtmlDocument() const;

 

 

 

    const string GetLastError() const;

 

 

 

    bool GetJScript(CComPtr<IDispatch>& spDisp);

 

 

 

    bool GetJScripts(CComPtr<IHTMLElementCollection>& spColl);

 

 

 

    bool CallJScript(const string strFunc,CComVariant* pVarResult = NULL);

 

 

 

    bool CallJScript(const string strFunc,const string strArg1,CComVariant* pVarResult = NULL);

 

 

 

    bool CallJScript(const string strFunc,const vector<string>& paramArray,CComVariant* pVarResult = NULL);  //关键看这个函数

 

 

 

    protected:

 

 

 

    void ShowError(LPCSTR lpszText);

 

 

 

    protected:

 

 

 

    CComPtr<IHTMLDocument2> m_spDoc;

 

 

 

    string m_strError;

 

 

 

    };

 

 

 

    CPP文件(代码片段):

 

 

 

    bool CWebPage::SetDocument(IDispatch* pDisp)

 

 

 

    {

 

 

 

    CHECK_POINTER(pDisp);

 

 

 

    m_spDoc = NULL;

 

 

 

    CComPtr<IDispatch> spDisp = pDisp;

 

 

 

    HRESULT hr = spDisp->QueryInterface(IID_IHTMLDocument2,(void**)&m_spDoc);

 

 

 

    if(FAILED(hr))

 

 

 

    {

 

 

 

    ShowError("Failed to get HTML document COM object");

 

 

 

    return false;

 

 

 

    }

 

 

 

    return true;

 

 

 

    }

 

 

 

 

 

 

 

    bool CWebPage::GetJScript(CComPtr<IDispatch>& spDisp)

 

 

 

    {

 

 

 

    CHECK_POINTER(m_spDoc);

 

 

 

    if (NULL == m_spDoc)

 

 

 

    {

 

 

 

    return false;

 

 

 

    }

 

 

 

    HRESULT hr = m_spDoc->get_Script(&spDisp);

 

 

 

    ATLASSERT(SUCCEEDED(hr));

 

 

 

    return SUCCEEDED(hr);

 

 

 

    }

 

 

 

    bool CWebPage::GetJScripts(CComPtr<IHTMLElementCollection>& spColl)

 

 

 

    {

 

 

 

    CHECK_POINTER(m_spDoc);

 

 

 

    HRESULT hr = m_spDoc->get_scripts(&spColl);

 

 

 

    ATLASSERT(SUCCEEDED(hr));

 

 

 

    return SUCCEEDED(hr);

 

 

 

    }

 

 

 

    bool CWebPage::CallJScript(const string strFunc,CComVariant* pVarResult)

 

 

 

    {

 

 

 

    vector<string> paramArray;

 

 

 

    return CallJScript(strFunc,paramArray,pVarResult);

 

 

 

    }

 

 

 

    bool CWebPage::CallJScript(const string strFunc,const string strArg1,CComVariant* pVarResult)

 

 

 

    {

 

 

 

    vector<string> paramArray;

 

 

 

    paramArray.push_back(strArg1);

 

 

 

    return CallJScript(strFunc,paramArray,pVarResult);

 

 

 

    }

 

 

 

    bool CWebPage::CallJScript(const string strFunc, const vector<string>& paramArray,CComVariant* pVarResult)

 

 

 

    {

 

 

 

    CComPtr<IDispatch> spScript;

 

 

 

    if(!GetJScript(spScript))

 

 

 

    {

 

 

 

    ShowError("Cannot GetScript");

 

 

 

    return false;

 

 

 

    }

 

 

 

    CComBSTR bstrMember(strFunc.c_str());

 

 

 

    DISPID dispid = NULL;

 

 

 

    HRESULT hr = spScript->GetIDsOfNames(IID_NULL,&bstrMember,1,

 

 

 

    LOCALE_SYSTEM_DEFAULT,&dispid);

 

 

 

    if(FAILED(hr))

 

 

 

    {

 

 

 

    ShowError(GetSystemErrorMessage(hr).c_str());

 

 

 

    return false;

 

 

 

    }

 

 

 

    const int arraySize = paramArray.size();

 

 

 

    DISPPARAMS dispparams;

 

 

 

    memset(&dispparams, 0, sizeof dispparams);

 

 

 

    dispparams.cArgs = arraySize;

 

 

 

    dispparams.rgvarg = new VARIANT[dispparams.cArgs];

 

 

 

    for( int i = 0; i < arraySize; i++)

 

 

 

    {

 

 

 

    CComBSTR bstr = paramArray[arraySize - 1 - i].c_str();

 

 

 

    bstr.CopyTo(&dispparams.rgvarg[i].bstrVal);

 

 

 

    dispparams.rgvarg[i].vt = VT_BSTR;

 

 

 

    }

 

 

 

    dispparams.cNamedArgs = 0;

 

 

 

    EXCEPINFO excepInfo;

 

 

 

    memset(&excepInfo, 0, sizeof excepInfo);

 

 

 

    CComVariant vaResult;

 

 

 

    UINT nArgErr = (UINT)-1; // initialize to invalid arg

 

 

 

    hr = spScript->Invoke(dispid,IID_NULL,0,

 

 

 

    DISPATCH_METHOD,&dispparams,&vaResult,&excepInfo,&nArgErr);

 

 

 

    delete [] dispparams.rgvarg;

 

 

 

 

 

 

 

    if(FAILED(hr))

 

 

 

    {

 

 

 

    ShowError(GetSystemErrorMessage(hr).c_str());

 

 

 

    return false;

 

 

 

    }

 

 

 

    if(pVarResult)

 

 

 

    {

 

 

 

    *pVarResult = vaResult;

 

 

 

    }

 

 

 

    return true;

 

 

 

    }

 

 

 

    测试的HTML页面

 

 

 

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

 

 

 

    <html xmlns="http://www.w3.org/1999/xhtml">

 

 

 

    <head>

 

 

 

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

 

 

 

    <title>myjstest</title>

 

 

 

    <script language="JavaScript" type="text/javascript">

 

 

 

    function f1()

 

 

 

    {

 

 

 

    alert("void");

 

 

 

    }

 

 

 

    function f2(values)

 

 

 

    {

 

 

 

    alert(values);

 

 

 

    }

 

 

 

    </script>

 

 

 

    </head>

 

 

 

    <body>

 

 

 

    </body>

 

 

 

    </html>

抱歉!评论已关闭.