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;
|