1. 程式人生 > >VC與JavaScript互動(二) ———— 呼叫JS函式

VC與JavaScript互動(二) ———— 呼叫JS函式

這一章,我們來動手實踐VC呼叫JS函式。

我們動手寫一個HTML,其中包含這樣一段JS程式碼:

<script type="text/javascript">
    function Add(value1, value2) {
        return value1 + value2;
    }
</script>

然後我們用WebBrowser載入這個HTML後,在VC中這樣來呼叫這個函式名為Add的JS函式:
//別忘了#include <MsHTML.h>
//m_WebBrowser是一個WebBrowser的Activex控制元件物件。
CComQIPtr<IHTMLDocument2> spDoc = m_WebBrowser.get_Document();
CComDispatchDriver spScript;
spDoc->get_Script(&spScript);

CComVariant var1 = 10, var2 = 20, varRet;
spScript.Invoke2(L"Add", &var1, &var2, &varRet);


spScript.Invoke2的作用是呼叫JS函式中名為Add的函式,傳入兩個引數,用varRet接收返回值。

可以看到,Invoke2呼叫成功後,varRet得到了返回值30。

但這樣的話一次只能接受一個返回值。

如果要一次接受多個返回值的話,怎麼辦呢?

我們可以讓JS返回一個JS中的Array陣列或Object物件。

當JS函式return一個Array或一個Object物件時,VC這邊的varRet將接受到一個代表該物件的IDispatch介面。我們仍然用CComDispatchDriver來管理這個IDispatch。用上一篇文章介紹的CComDispatchDriver的四個方法:

GetProperty

GetPropertyByName

PutProperty

PutPropertyByName

來從這個Array或Object物件中取出我們要的資料。

實踐是檢驗真理的唯一標準,讓我們再來寫一個JS函式:

<script type="text/javascript">
    function Add(value1, value2) {
        var array = new Array();
        array[0] = value1;
        array[1] = value2;
        array[2] = value1 + value2;
        return array;
    }
</script>

然後在VC中這樣寫:
CComQIPtr<IHTMLDocument2> spDoc = m_WebBrowser.get_Document();
CComDispatchDriver spScript;
spDoc->get_Script(&spScript);

CComVariant var1 = 10, var2 = 20, varRet;
spScript.Invoke2(L"Add", &var1, &var2, &varRet);
	
CComDispatchDriver spArray = varRet.pdispVal;
//獲取陣列中元素個數,這個length在JS中是Array物件的屬性,相信大家很熟悉
CComVariant varArrayLen;
spArray.GetPropertyByName(L"length", &varArrayLen);
//獲取陣列中第0,1,2個元素的值:
CComVariant varValue[3];
spArray.GetPropertyByName(L"0", &varValue[0]);
spArray.GetPropertyByName(L"1", &varValue[1]);
spArray.GetPropertyByName(L"2", &varValue[2]);


可以看到,10,20,30,這三個JS函式返回的值已經躺在我們的varValue[3]裡了。

當然,如果不知道JS返回的Array物件裡面有幾個元素,我們可以在VC這邊獲取它的length屬性,然後在一個迴圈中取出陣列中的每個值。

如果我們的JS函式返回一個包含有多個屬性值的Object物件,VC這邊該如何接收呢?

讓我們再來寫一個JS函式:

<script type="text/javascript">
    function Add(value1, value2) {
        var data = new Object();
        data.result = value1 + value2;
        data.str = "Hello,我是小明!";
        return data;
    }
</script>

然後在VC中我們這樣接收:
CComQIPtr<IHTMLDocument2> spDoc = m_WebBrowser.get_Document();
	CComDispatchDriver spScript;
	spDoc->get_Script(&spScript);

	CComVariant var1 = 10, var2 = 20, varRet;
	spScript.Invoke2(L"Add", &var1, &var2, &varRet);
	
	CComDispatchDriver spData = varRet.pdispVal;
	CComVariant varValue1, varValue2;
	spData.GetPropertyByName(L"result", &varValue1);
	spData.GetPropertyByName(L"str", &varValue2);


我們從JS返回的Object物件裡取出了它的兩個屬性,result和str,分別是一個整形資料和一個字串。

這裡JS程式碼是我們自己寫的,在VC這邊當然事先知道這個JS函式返回的物件有result和str這兩個屬性。

如果JS程式碼不是我們寫的,或者它的屬性是事先不能確定的,該怎麼辦呢?答案是使用IDispatchEx介面來列舉這個物件的相關資訊(方法名、屬性名)。這個現在暫時不講,在後續的文章中會講。

當然,JS不只可以返回Object物件,返回什麼物件都可以,當返回一個物件而非基本資料型別(整形、浮點、字串)時,VC這邊收到的返回值是一個IDispatch,然後我們需要呼叫GetPropertyByName方法從這個IDispatch代表的物件中取出它的屬性來。

JS中生成的物件和陣列,傳遞給VC後,可以用CComDispatchDriver方便的讀取,但如果要在VC這邊生成一個物件或陣列傳遞給JS該怎麼辦呢? 很多時候我們用VC呼叫JS函式的時候,需要傳遞很多引數給它,引數少還好辦,給JS函式多寫幾個形參就行了,可是引數很多,多達數十個數百個怎麼辦?傳遞物件或陣列才是好辦法。JS中的物件和陣列傳到VC這邊後就變成了一個IDispatch*,那麼同理我們構造一個IDispatch*傳給JS不就行了嗎?說起來容易做起來麻煩,具體實現可以看下一章《VC與JavaScript互動(三) ———— JS呼叫C++》,但實在是太麻煩了。 用JSON就行了!VC想傳遞什麼給JS,只需把要傳遞的資料放到JSON裡,然後把JSON字串扔給JS,接下來JS用JSON.stringify()就把這個JSON字串變成JS中的陣列或物件了。 如此一來,VC與JS互動只需傳遞字串就行了,VC這邊生成JSON的話手工拼接一下字串也很簡單,也可用一些庫來實現,如RapidJSON、jsoncpp、Boost.PropertyTree等等。

這樣一來,VC呼叫JS函式,傳遞引數給JS和JS返回返回值給VC,大致就都會了。

對於CComVariant包裝的VARIANT這種智慧型變數,不瞭解的可以到網上看下相關資料。《深入解析ATL》之類的書上均有介紹。

值得注意的是ATL提供的這些CCom開頭的智慧包裝類,並不依賴於ATL的動態庫。因為我在VC專案中並沒有選擇連結ATL,程式除錯執行時程序載入的模組中也有沒有ATL100.dll之類的模組載入。大家可以放心使用而不用擔心依賴上ATL。

VC呼叫JS函式沒問題了。那麼JS函式如何呼叫VC呢?我們將在下一篇文章中慢慢道來。


相關推薦

VCJavaScript互動() ———— 呼叫JS函式

這一章,我們來動手實踐VC呼叫JS函式。 我們動手寫一個HTML,其中包含這樣一段JS程式碼: <script type="text/javascript"> function Add(value1, value2) { return

VCJavaScript互動(三) ———— JS呼叫C++

太監的原因:     時隔兩年,VC與JavaScript互動系列的最後一篇關於JavaScript如何呼叫c++的文章終於出爐了。為什麼會隔了那麼久?因為本來打算太監的,可是看到熱情的網友們的眼神,從期望變成了失望,在我的心裡激起了層層波瀾。兩年後的今天,還是堅持

VCJavaScript互動(四) ———— WebBrowser或CHtmlView中輕鬆遮蔽指令碼錯誤(JavaScript)

1.什麼是javascript指令碼錯誤 1.1    概述 JavaScript指令碼錯誤包含“執行時錯誤”和“語法錯誤”。 1.2    JavaScript“語法錯誤” JavaScript語法錯誤是指當 JavaScript語句違反了 JavaScript指令碼語言

Java R 互動--Java呼叫R函式-Rserver方式

JAVA很適合開發應用系統,但是數學建模和計算能力非其所長,如果該系統需要進行大量的統計或者優化的計算,呼叫R是一種很好的方式。JAVA負責系統的構建,R用來做運算引擎,從而實現應用型和分析性相結合的系統。 首先要介紹的是Rserve的方式,這是一個基於TCP

UIWebViewjavascript互動通過頁面的響應事件獲取頁面輸入框內的值

接上篇文章,上篇文章實現了UIwebview對html檔案的載入和對js事件的響應,但是對html頁面上輸入的值沒有獲取。 今天就來說說這個首先要用到工具類WebViewJavascriptBridge 下載地址 然後將工具類匯入到專案中。 其中te

FlexJavaScript互動呼叫函式

一、在JavaScript中呼叫Flex方法  在 Flex 應用中,需要在方法列表中新增指定的公用方法,這樣Flex中的方法才能被JS呼叫到。在Flex中需要通過呼叫addCallback()可以把一個方 法新增到此列表中。 addCallback將一個ActionScr

WKWebviewJavaScript 互動)監聽遠端網頁點選事件

引言 監聽網頁的按鈕的點選事件,並且網頁不是我們招呼一聲對方就能改的。那麼繼續。 正文 1.WKUserScript 先介紹WebKit框架一個類WKUserScript: 核心方法,傳入JS程式碼字串,返回給我們一個WKUserScr

VC++ CHtmlViewJavascript互動

轉載自:‍http://blog.sina.com.cn/s/blog_3fa68f2d01000bm5.html‍如何在CHtmlView中實現與HTML頁面使用window.external對像進行互動。1、在類定義時新增DECLARE_DISPATCH_MAP()如:

前臺js後臺C#互相呼叫 & JS於HTML互動

C#程式碼與javaScript函式的相互呼叫? 問: 1.如何在JavaScript訪問C#函式? 2.如何在JavaScript訪問C#變數? 3.如何在C#中訪問JavaScript的已有變數? 4.如何在C#中訪問JavaScript函式?問題1答案如下: ja

新手學習日記-Javascript和Html 1:如何在html中呼叫Js函式

HTML組成網頁,CSS組織網頁,Javascript可以給網頁新增複雜操作。首先要明白,HTML是靜態的,要想實現複雜的可變的操作(比如函式,計算結果等)必須使用Javascript進行操作。Q.如何在Html中獲取Javascript函式的值HTML是靜態的,即使將Jav

Android:WebViewJavascript互動(相互呼叫引數、傳值)

Android中可以使用WebView載入網頁,同時Android端的java程式碼可以與網頁上的javascript程式碼之間相互呼叫。 效果圖: (一)Android部分: 佈局程式碼: <LinearLayout xmlns:android="http://s

FlexJavaScript互動中如何用Flex呼叫JavaScript

本文和大家重點討論一下Flex與JavaScript的互動:Flex呼叫JavaScript或者被JavaScript呼叫,在Flex中呼叫JavaScript最簡單的方法是使用ExternalInterface(),可以使用此API呼叫任意JavaScript,傳遞引數,獲

lua c++互動呼叫函式

</pre><pre name="code" class="cpp"> 對c/c++ 與lua的互動呼叫函式做一個小總結 #include <iostream>

MVC Razorjavascript混編(js中嵌入razor)

razor語法 js代碼 module new ext activit pageutil script 輸出 其中的關鍵是輸出js上的純文本內容,讓瀏覽器解析為其中的js代碼 <script> BUI.use(‘common/main‘,functio

在 Cef 中實現 C++ JavaScript 互動場景分析

此文已由作者鄧佳佳授權網易雲社群釋出。 歡迎訪問網易雲社群,瞭解更多網易技術產品運營經驗 本文主要介紹 CEF 場景中 C++ 和 JavaScript 互動(以下簡稱 JS Bridge)中的一些重要節點,包括了 C++/JavaScript 的方法註冊、方法呼叫、回撥管理。以下是一些

JavaScript學習js常用事件操作方法)

Dom滑鼠事件 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style>

如何從 VC WebBrowser 應用程式中呼叫指令碼函式

為了呼叫指令碼函式存在的網頁上,您必須使用自動化 ; 換句話說,IDispatch。 使用以下步驟來呼叫指令碼函式從 Visual C++ 應用程式的網頁上存在的: 獲取在 HTML 文件的 IDispatch。 呼叫利用 IDispatch:: GetIDsOfName

三十三、Linux 程序訊號——中斷系統呼叫函式可重入性

33.1 中斷系統呼叫 程序呼叫 “慢” 系統呼叫時,如果發生了訊號,核心會重啟系統呼叫。 慢系統呼叫 可能會永久阻塞的系統呼叫 從終端裝置、管道或網路裝置上的檔案讀取 向上述檔案寫入 某些裝置上的檔案開啟 pause 和 wait 系統呼叫

html中的button按鈕呼叫js函式和提交表單傳遞引數

1.button的type設定為button 而不用submit,並新增onclick方法呼叫js函式 <input type="button" name="confirmAlter" value="確認修改" onclick="changeInfo(form1.co

PHPJavascript互動

Javascript簡介:JavaScript是一種基於物件和事件驅動的指令碼語言。Javascript語言與靜態html標籤結合使用,可以再靜態的HTML頁面上實現與使用者的互動性操作。 Javascript優點:能夠有效地節省客戶端與伺服器的互動時間,大大節省伺服器資源。即JavaS