Delphi Programming / Object Pascal
[掲載 2020年05月25日] [更新 2020年05月25日] Delphi 一般・その他 |
TWebBrowser における JavaScript の実行と戻り値の取得 |
動作確認等 |
Windows 7 U64(SP1) + Delphi XE5(UP2) Pro VCL-32 |
Delphi の TWebBrowser コンポーネントで JavaScript を実行し,戻り値や JavaScript 内の変数の値を取得するサンプルです.
参考リンクの 4 番目の記事にも JavaScript を実行するサンプルがあります.window.external のサンプルは、JavaScript 内から Delphi のメソッドを実行するサンプルです. |
本ページのサンプルコードでは,インターフェイスの確認,あるいはオブジェクトのチェックを省略しています.以下のようにしておけば,エラーの発生が抑止でき,例外でプログラムが停止することを抑止できます. |
if not Supports(WebBrowser1.Document, IHTMLDocument3, LIDocument3) then Exit;
LIElement := LIDocument3.getElementById('result1');
if LIElement = nil then Exit;
QueryInterface 関数を使用する場合は,以下のように処理できます. |
if WebBrowser1.Document.QueryInterface(IHTMLDocument3, LIDocument3) <> S_OK then Exit;
01_JavaScript の引数なしの関数の実行 |
IHTMLWindow2 の execScript メソッドを使用すると,TWebBrowser コンポーネントで HTML コード内に書かれている JavaScript の関数を実行することができます.その例です.
実行する JavaScript の関数名は文字列として渡します.このサンプルは引数なしの関数を実行する例です.引数がない場合は,関数名の末尾に () が必要です.
このサンプルでは,フォーム生成時に HTML コードを読み込んで TWebBrowser で表示しています. |
|
図1
JavaScript の関数の実行結果
- このデイアログは JavaScript 内の関数が表示している
- TWebBrowser のテキストも JavaScript の関数内のコードで表示している
|
まず,以下のフォルダにライブラリのパスを通しておきます. |
リスト1
テストに使用した HTML コート.ファイル名は JaveScriptTest.html |
<!DOCTYPE html>
<html>
<head>
<script>
var count = 0;
function testFunction() {
ret = confirm("確認したら OK をクリック");
if (ret == true){
count = count + 1;
resstr = "確認済み " + count + " 回目";
document.body.insertAdjacentHTML("beforeend", resstr);
}
}
</script>
</head>
<body>
</body>
</html>
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.OleCtrls, SHDocVw,
Vcl.StdCtrls, Vcl.ExtCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
WebBrowser1: TWebBrowser;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses
MSHTML;
{$R *.dfm}
//=============================================================================
// フォーム生成時の処理
// テスト用の HTML コードを読み込んで表示
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
var
LURL : string;
begin
LURL := ExtractFilePath(Application.ExeName) + 'JaveScriptTest.html';
WebBrowser1.Navigate(LURL);
end;
//=============================================================================
// JavaScript の関数の実行
// 引数なしの場合
//
// uses に MSHTML が必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LIDocument2 : IHTMLDocument2;
LIWindow2 : IHTMLWindow2;
LJScriptStr : string;
begin
LIDocument2 := (WebBrowser1.Document as IHTMLDocument2);
LIWindow2 := LIDocument2.parentWindow;
try
LJScriptStr := 'testFunction()';
LIWindow2.execScript(LJScriptStr, 'JavaScript');
except
end;
end;
end.
02_JavaScript の文字列型引数付き関数の実行 |
JavaScript の関数の引数に文字列を渡す場合は,文字列をダブルクォーテーションで括ります.
ダブルクォーテーションを含む文字列を文字列として引数に渡します. |
|
図2
JavaScript の関数の実行結果ー
- このデイアログは JavaScript 内の関数が表示している
- 表示している値は JavaScript の関数の引数に渡した文字列
|
リスト3
テストに使用した HTML コート.ファイル名は JaveScriptTest.html |
<!DOCTYPE html>
<html>
<head>
<script>
function testFunction(arg) {
alert (arg);
}
</script>
</head>
<body>
</body>
</html>
リスト4
テスト用のフォームのユニットのコード
フォーム OnCreatae イベントのコードは最初のサンプルと同じ |
//=============================================================================
// JavaScript の関数の実行
// 引数が文字列の場合
// 引数の文字列をシングルまたはダブルクォーテーションで括る
//
// uses に MSHTML が必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LIDocument2 : IHTMLDocument2;
LIWindow2 : IHTMLWindow2;
LArgStr : string;
LJScriptStr : string;
begin
LIDocument2 := (WebBrowser1.Document as IHTMLDocument2);
LIWindow2 := LIDocument2.parentWindow;
try
// 以下 (シングルクォーテーション 3 つ) でもよい
// LArgStr := '''引数の文字列!''';
LArgStr := '"引数の文字列!"';
LJScriptStr := 'testFunction(' + LArgStr + ')';
LIWindow2.execScript(LJScriptStr, 'JavaScript');
except
end;
end;
文字列が変数の場合は,
変数名をダブルクォーテーションで括ります. |
// 文字列が変数の場合
// 文字列にダブルクォーテーションを追加する
// LArgStr := '"' + LArgStr + '"';
LArgStr := '引数の文字列!';
LArgStr := AnsiQuotedStr(LArgStr, '"');
03_JavaScript の数値型引数付き関数の実行 |
JavaScript の関数の引数に数値を渡す場合は,数値を文字列にして引数に渡します. |
|
図3
JavaScript の関数の実行結果
- このデイアログは JavaScript 内の関数が表示している
- 表示値は JavaScript の関数の引数に渡した数値と関数内の値の加算値
|
リスト6
テストに使用した HTML コート.ファイル名は JaveScriptTest.html |
<!DOCTYPE html>
<html>
<head>
<script>
function testFunction(arg) {
intval = 50000000 + arg;
alert (intval);
}
</script>
</head>
<body>
</body>
</html>
リスト7
テスト用のフォームのユニットのコード
フォーム OnCreatae イベントのコードは最初のサンプルと同じ |
//=============================================================================
// JavaScript の関数の実行
// 引数が数値の場合は文字列にして渡す
//
// uses に MSHTML が必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LIDocument2 : IHTMLDocument2;
LIWindow2 : IHTMLWindow2;
LArgInt : Integer;
LJScriptStr : string;
begin
LIDocument2 := (WebBrowser1.Document as IHTMLDocument2);
LIWindow2 := LIDocument2.parentWindow;
try
LArgInt := 123450;
LJScriptStr := 'testFunction(' + IntToStr(LArgInt) + ')';
LIWindow2.execScript(LJScriptStr, 'JavaScript');
except
end;
end;
04_JavaScript の実行結果 ( JavaScript 内の変数の値) を取得 |
JavaScript 内の変数の値を Delphi 側のコードで取得する例です.JajaScript の関数の実行結果を特定の変数に代入しておけば,その変数の値を取得することができます.
TWebBrowser に表示する HTML コードに以下の要素 (コード) を追加しておきます.この例では id の値は result1 となっています.この id の値 (文字列) は,対象の HTML コード内にはない一意の値とします.
|
<input type='hidden' id='result1' value=''>
JavaScript 内の関数内で,この要素の value 属性の値に,Delphi 側で取得したい値を代入して置き換えます.この置き換えた値を DOM 操作で取得します.
このサンプルの方法では,JavaScript の関数の return 値は取得できません. |
|
図4
JavaScript の関数の実行結果
|
リスト8
テストに使用した HTML コート.ファイル名は JaveScriptTest.html |
<!DOCTYPE html>
<html>
<head>
<script>
function testFunction() {
retval = 50000000;
document.getElementById('result1').value=retval;
}
</script>
</head>
<body>
<input type='hidden' id='result1' value=''>
</body>
</html>
リスト9
テスト用のフォームのユニットのコード
フォーム OnCreatae イベントのコードは最初のサンプルと同じ |
//=============================================================================
// JavaScript の関数の実行
// 関数の戻り値を取得( JavaScript 内の変数の値の取得 )
//
// uses に MSHTML が必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LIDocument2 : IHTMLDocument2;
LIDocument3 : IHTMLDocument3;
LIWindow2 : IHTMLWindow2;
LIElement : IHTMLElement;
LJScriptStr : string;
LValueText : string;
begin
LIDocument2 := (WebBrowser1.Document as IHTMLDocument2);
LIWindow2 := LIDocument2.parentWindow;
try
LJScriptStr := 'testFunction()';
LIWindow2.execScript(LJScriptStr, 'JavaScript');
// JavaScrip の関数の実行結果を取得
// この例では id の値が result1 の value 属性の値を取得
LIDocument3 := WebBrowser1.Document as IHTMLDocument3;
LIElement := LIDocument3.getElementById('result1');
LValueText := LIElement.getAttribute('value', 0);
MessageBox(Handle, PChar(LValueText), '結果', MB_ICONINFORMATION);
except
end;
end;
05_JavaScript の関数の return 値の取得 |
JavaScript の関数の return 値を取得する例です.
方法としては前項と同じですが,JavaScript の eval 関数を使用して,以下の要素の value 属性に関数の実行結果を代入します.この置き換えた値を Delphi 側から DOM 操作で取得します.
本サンプルては,以下のコードを実行時に HTML の要素として挿入しています.Button2 クリックで挿入するようにしていますので,Button2 をクリックしてから Button1 をクリックしないとスクリプトのエラーが発生します. |
<input type='hidden' id='result1' value=''>
|
図5
JavaScript の関数の実行結果
- JavaScript の関数の return 値を取得して表示
- Button2 をクリックしてから Button1 をクリックする
|
リスト10
テストに使用した HTML コート.ファイル名は JaveScriptTest.html |
<!DOCTYPE html>
<html>
<head>
<script>
function testFunction() {
return "retrun value";
}
</script>
</head>
<body>
</body>
</html>
リスト11
テスト用のフォームのユニットのコード
フォーム OnCreatae イベントのコードは最初のサンプルと同じ |
//=============================================================================
// JavaScript の関数の実行
// 関数の戻り値を取得
//
// uses に MSHTML が必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LIDocument2 : IHTMLDocument2;
LIDocument3 : IHTMLDocument3;
LIWindow2 : IHTMLWindow2;
LIElement : IHTMLElement;
LIdValue : string;
LJScriptStr : string;
LValueText : string;
LJSText : string;
begin
LIdValue := 'result1';
LIDocument2 := (WebBrowser1.Document as IHTMLDocument2);
LIWindow2 := LIDocument2.parentWindow;
try
LJScriptStr := 'testFunction()';
// 関数の実行結果を指定要素の value 属性の値にセットするためのコード
LJSText := 'eval("tagelement = document.getElementById(''' + LIdValue + ''');'
+ 'tagelement.value =' + LJScriptStr + '");';
LIWindow2.execScript(LJSText, 'JavaScript');
// JavaScrip の関数の実行結果を取得
// この例では id の値が result1 の value 属性の値を取得
LIDocument3 := WebBrowser1.Document as IHTMLDocument3;
LIElement := LIDocument3.getElementById(LIdValue);
LValueText := LIElement.getAttribute('value', 0);
MessageBox(Handle, PChar(LValueText), '結果', MB_ICONINFORMATION);
except
end;
end;
//=============================================================================
// 実行時に HTML のノードを追加
// input タグの例
//
// uses に MSHTML が必要
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
LIDocument2 : IHTMLDocument2;
LIDocument3 : IHTMLDocument3;
LIElement : IHTMLElement;
LIdValue : string;
LBodyNode : IHTMLDOMNode;
LNewNode : IHTMLDOMNode;
begin
LIdValue := 'result1';
if not Supports(WebBrowser1.Document, IHTMLDocument2, LIDocument2) then Exit;
if not Supports(WebBrowser1.Document, IHTMLDocument3, LIDocument3) then Exit;
// コードが追加済みなら作成しない
if LIDocument3.getElementById(LIdValue) <> nil then Exit;
// input タグの要素を作成して属性を設定
LIElement := LIDocument2.createElement('input');
LIElement.setAttribute('type', 'hidden', 0);
LIElement.id := LIdValue;
LIElement.setAttribute('value', '', 0);
if not Supports(LIDocument2.body, IHTMLDOMNode, LBodyNode) then Exit;
if not Supports(LIElement, IHTMLDOMNode, LNewNode) then Exit;
// HTML に コードを追加
LBodyNode.appendChild(LNewNode);
end;
06_JavaScript のコードを実行時に HTML 要素として追加 |
実行時に,HTML の要素として JavaScript の関数のコードを挿入する例です.
このサンプルでは,関数のコードを書いたファイルを読み出していますが,コード中で作成することも考えられます. |
|
図6
JavaScript の関数の実行結果
- このデイアログは JavaScript 内の関数が表示している
|
リスト12
テストに使用した HTML コート.ファイル名は JaveScriptTest.html |
<!DOCTYPE html>
<html>
<head>
</head>
<body>
</body>
</html>
リスト13
実行時に HTML に追加したコード.javaScript の関数のコード |
function testFunction() {
alert ("実行確認ダイアログ");
}
リスト14
テスト用のフォームのユニットのコード
フォーム OnCreatae イベントのコードは最初のサンプルと同じ |
//=============================================================================
// JavaScript の関数の実行
// JavaScirp のコードを実行時に HTML に追加
//
// uses に MSHTML が必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LStrList : TStringList;
LIDocument2 : IHTMLDocument2;
LIWindow2 : IHTMLWindow2;
LIDOMNode : IHTMLDOMNode;
begin
LIDocument2 := (WebBrowser1.Document as IHTMLDocument2);
LIWindow2 := LIDocument2.parentWindow;
LStrList := TStringList.Create;
try
LStrList.LoadFromFile('JavaTest_JS.txt');
// JavaScript のノードを追加して,そこに関数のコードを追加
LIDOMNode := LIDocument2.createElement('script') as IHTMLDOMNode;
(LIDOMNode as IHTMLScriptElement).text := LStrList.Text;
(LIDocument2.body as IHTMLDOMNode).appendChild(LIDOMNode);
// JavaScript の関数を実行
LIWindow2.execScript('testFunction()', 'JavaScript');
finally
FreeAndNil(LStrList);
end;
end;
|