Delphi Programming / Object Pascal

[掲載 2010年06月08日] [更新 2017年10月20日] Delphi サンプルプログラム集 |
| 950_Delphi で VBScript を操作 |
| 動作確認等 |
Windows XP(SP3) + Delphi 2010(UP5) Pro + vbscript.dll 5.7.0.16535
Windows 7 U64 + Delphi 2010(UP5) Pro + vbscript.dll 5.8.7600.16546 |
 |
950_VBScript.zip [3,662 KB] 2017年10月20日版 (EXE 同梱) |
- 2011年04月15日
- サンプル [03] に数式処理関係のリンクを追加
|
| Delphi で VBScript を操作 - タイプライブラリの取り込み |
VBScript (Microsoft Visual Basic Scripting Edition:VBS) は,マイクロソフトが提供しているスクリプト言語です。VB (Visual Basic) のサブセット版の言語仕様となっています。
言語仕様の詳細については、マイクロソフトの VBScript ユーザーズ ガイドで確認してださい。
ネット上にはマイクロソフトのスクリプトセンターをはじめ、VBScript で書かれたサンプルコードが多くあります。これらのコードを Delphi で利用したり自分で VBScritp のコードを作成する場合の参考となるかも知れないサンプルです。[VBScript 関数リファレンス] というサイトが見やすい様です (記事の掲載日等は、多くのサイトの記事がそうであるように不明です)。
このページのサンプルでは、[タイプライブラリの取り込み] で作成した MSScriptControl_TLB.pas を使用しています。タイプライブラリの取り込みでは、コンポーネントラッパーを作成して、コンポーネントとして登録します。
サンプルプログラム集のサンプルを書くときはいつも、サンプルの内容に迷うのですが、このページのサンプルもあまりいい例でないかも知れません。このページのサンプルは Fusa さんのサイトの記事を参考にしています。
|
[備考]
VBScript と後述の JScript は、WSH (Windows Script Host) という Windows のスクリプト実行環境で使用可能なスクリプト言語です。WSH 自身にはシェルの機能は実装されていません。
Windows 7 で標準実装された PowerShell というスクリプト実行環境は、独自のスクリプト言語を実装し、コマンドプロンプトの強化版としてのシェルの機能を実装しています。 |
- 図1
- [タイプライブラリの取り込み] で MSScriptControl_TLB.pas ファイルを作成
|
 |
VBScript のコードはテキストファイルです。コードを書いたテキストファイルを、拡張子 vbsで 保存すると、それが VBScript のファイルとなります。これをダブルクリック等で実行します。
下図は添付のサンプルの簡単な実行例です。 |
 |
図2
添付の VBS ファイル
|
 |
図3
下のコードの実行結果 |
| 次の図は FileProperties1.vbs の実行結果です。コード内の str 変数の内容を表示しています。 |
 |
図4
下のコードの実行結果
|
リスト2
FileProperties1.vbs のコード |
' ファイルのプロパティをダイアログで表示する
Set FS = CreateObject("Scripting.FileSystemObject")
Set F = FS.GetFile("BW_Delphi.jpg")
str = ""
str = str & "ファイル名: " & F.Name & vbCrLf
str = str & "最終アクセス: " & F.DateLastAccessed & vbCrLf
str = str & "最終変更: " & F.DateLastModified & vbCrLf
str = str & "サイズ: " & F.Size
MsgBox str
| 次の図は FileProperties2.vbs の実行結果です。コードの 1 行を実行するたびにその内容を表示するようになっているので、[OK] ボタンをクリックすると次の値を表示します。 |
 |
図5
下のコードの実行結果
|
リスト3
FileProperties2.vbs のコード |
' ファイルのプロパティを順番にダイアログで表示する
Set FS = CreateObject("Scripting.FileSystemObject")
Set F = FS.GetFile("BW_Delphi.jpg")
WScript.echo "ファイル名: " & F.Name
WScript.echo "最終アクセス: " & F.DateLastAccessed & vbCrLf
WScript.echo "最終変更: " & F.DateLastModified & vbCrLf
WScript.echo "サイズ: " & F.Size
| 当然ですが、ダブルクリックで実行するということは、以下のように、ShellExecute 関数等を使用して実行することと同じです。引数付きで実行する VBS のコードは、ShellExecute 関数の 4 番目に引数の値を指定することになります。 |
procedure TForm1.Button1Click(Sender: TObject);
begin
ShellExecute(Handle,'open','SimpleTest.vbs', nil, nil, SW_HIDE);
end;
| 上の VBScript 程度のコードであれば、uses に ComObj を追加して、下に示すように、Delphi のコードに移植して実行ということも考えられます。しかし、VBScript 独自の命令を使用していると簡単に移植できない場合もあります。そのような場合、VBScript のコードを Delphi から実行できると便利です。 |
procedure TForm1.Button1Click(Sender: TObject);
var
FS : OleVariant;
F : OleVariant;
AStr : String;
begin
FS := CreateOleObject('Scripting.FileSystemObject');
F := FS.GetFile('BW_Delphi.jpg');
AStr := 'ファイル名: ' + VarToStr(F.Name) + sLineBreak
+ '最終アクセス: ' + VarToStr(F.DateLastAccessed) + sLineBreak
+ '最終更新: ' + VarToStr(F.DateLastModified) + sLineBreak
+ 'サイズ: ' + VarToStr(F.Size);
ShowMessage(AStr);
end;
[備考]
Delphi の場合は、COM オブジェクトの生成に CreateOleObject を使用します。VB や VBS で使用している CreateObject という関数は、Delphi にはありません。また、VB, VBS の GetObject は Delphi では GetActiveOleObject に相当します。VB, VBS の GetObject はオブジェクトの参照、Windows API の GetObject はオブジェクトの情報取得用の関数です。
Delphi で使用する GetObject 関数は、クラススコープがあれば、そのクラスあるいはコンポーネントのオブジェクトを取得し、単に GetObject とした場合は Windows API の関数を意味し、明確に区別することができます。
VB や VBS の vbCrLf (改行文字) は、Delphi では sLineBreak です。
|
| 02_VBScript のコードを Delphi で実行 |
前の VBScript のコードを Delphi で実行します。もちろん ShellExecuteEx や CreateComObject でVBS ファイルを指定して実行することもできますが、スクリプトの操作が困難になります。ここでは[タイプライブラリの取り込み] で作成した MSScriptControl_TLB を uses して使用します。
Button1Click では、VBS のコードを実行時に作成して、TScriptControl の ExecuteStatement メソッドを実行します。
Button2Click では、VBScript のテキストを読込んでから実行します。Button3Click ではそのコードを 1行 づつ実行する場合です。結果は Button2Click と同じとなります。 |
 |
図6
設計時画面 |
 |
図7
Button1 クリック |
 |
図8
Button2 クリック |
リスト4
Delphi で VBScript のコードを実行 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, MSScriptControl_TLB, ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// VBScriptのコードをDelphiのコードで作成して実行する例
// VBScriptのExecuteStatementメソッドを使用する
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
VBSpt : TScriptControl;
begin
//VBScriptオブジェクトを生成
VBSpt := TScriptControl.Create(Self );
VBSpt.Language := 'VBScript';
try
VBSpt.ExecuteStatement('msgbox("こんにちは。お元気ですか。") ');
finally
FreeAndNil(VBSpt);
end;
end;
//=============================================================================
// VBScriptのコードをDelphiで読込んで実行する例
// VBScriptのExecuteStatementメソッドを使用する
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
VBSpt : TScriptControl;
SL : TStringList;
begin
//VBScriptオブジェクトを生成
VBSpt := TScriptControl.Create(Self);
VBSpt.Language := 'VBScript';
//コードを格納するTStringList生成
SL := TStringList.Create;
try
//コードを読込んで実行
SL.LoadFromFile('FilePropeties1.vbs');
VBSpt.ExecuteStatement(SL.Text);
finally
FreeAndNil(SL);
FreeAndNil(VBSpt);
end;
end;
//=============================================================================
// VBScriptのコードをDelphiで読込んで1行づつ実行する例
// VBScriptのExecuteStatementメソッドを使用する
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
var
VBSpt : TScriptControl;
SL : TStringList;
i : Integer;
begin
//VBScriptオブジェクトを生成
VBSpt := TScriptControl.Create(Self);
VBSpt.Language := 'VBScript';
//コードを格納するTStringList生成
SL := TStringList.Create;
try
//コードを読込んで1行づつ実行
SL.LoadFromFile('FilePropeties1.vbs');
for i := 0 to SL.Count - 1 do begin
VBSpt.ExecuteStatement(SL[i]);
end;
finally
FreeAndNil(SL);
FreeAndNil(VBSpt);
end;
end;
end.
TScriptControl には Eval というメソッドがあります。これは後述のように、VBScript の実行結果を取得する時に使用しますが、式の評価にも使用できます。その例です。文字列で与えた計算式を実行でき、関数電卓に似たようなことができます。
Delphi で数式処理を行うには、以下のリンクも参考になるでしょう。
[Cindy components のインストール手順] で紹介している Cindy components 群にも TcyMathParser というコンポーネントがあります。 |
| 以上は、いわゆる数式処理や関数電卓のようなものですが、Microsoft Word (ワード) の数式エディタや pTex (Publishing TeX)、LaTeX (ラテフ) のような数式エディタを実装するためのコンポーネントのようなものもネット上で見た記憶があります。 |
 |
図9
設計時画面 |
 |
図10
Button1 クリック
|
 |
図11
Button2 クリック
|
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, MSScriptControl_TLB, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Edit1: TEdit;
Label1: TLabel;
Label2: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormShow(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// Edit1にテスト用の数式をセット
//=============================================================================
procedure TForm1.FormShow(Sender: TObject);
begin
Edit1.Text := '(10 + 20) / 5';
end;
//=============================================================================
// VBScriptのEval関数(文字列で与えられた数式を計算)の簡単な使用例
// 文字列で与えられた計算式の計算結果を表示
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
VBSpt : TScriptControl;
begin
//VBScriptオブジェクトを生成
VBSpt := TScriptControl.Create( Self );
VBSpt.Language := 'VBScript';
try
//計算結果を表示
Label2.Caption := VarToStr(VBSpt.Eval('sin(90) + log(10)')) ;
finally
FreeAndNil(VBSpt);
end;
end;
//=============================================================================
// VBScriptのEval関数(文字列で与えられた数式を計算)の簡単な使用例
// Edit1のTextプロパティの文字列式を計算する
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
VBSpt : TScriptControl;
begin
//VBScriptオブジェクトを生成
VBSpt := TScriptControl.Create( Self );
VBSpt.Language := 'VBScript';
try
//計算結果を表示
Label2.Caption := VarToStr(VBSpt.Eval(Edit1.Text)) ;
finally
FreeAndNil(VBSpt);
end;
end;
end.
上のサンプルでは、VBScript を実行して、その結果も VBScript のダイアログで表示していました。この結果を Delphi 側で表示するために、TScriptControl の Evalメソッドの引数に VBScript 内の変数名を指定して、その値を取得します。
そのために、元の VBScript コードの表示部分を削除しておきます。サンプルではそのコードを TMemo に表示するようにしてみました。 |
 |
図12
設計時画面 |
 |
図13
Button1 クリック
|
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, MSScriptControl_TLB, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
Panel1: TPanel;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// ファイルからVBScriptのコードを読込んで実行
// 実行するのは表示コード部分のないVBSコード。表示はDelphiで実行
//
// このコードではTStringListに読込んで実行しているが、Memo1.Textを実行しても
// 同じ。結果の表示を他のコントロールに表示することを考えてTStringListを使用
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
VBSpt : TScriptControl;
SL : TStringList;
AFileName : String;
AType : String;
ModifiyDate : TDateTime;
AccessDate : TDateTime;
ASize : Int64;
begin
Memo1.Lines.BeginUpdate;
//VBScriptオブジェクトを生成
VBSpt := TScriptControl.Create(Self);
VBSpt.Language := 'VBScript';
//コードを格納するTStringList生成
SL := TStringList.Create;
try
//コードを読込んで実行
SL.LoadFromFile('FilePropeties.txt');
VBSpt.ExecuteStatement(SL.Text);
Memo1.Text := SL.Text;
Memo1.Lines.Add('');
Memo1.Lines.Add(' ---------- 結果 ----------');
Memo1.Lines.Add('');
//実行結果から値を取得
AFileName := VarToStr(VBSpt.Eval('F.Name'));
AType := VarToStr(VBSpt.Eval('F.Type'));
AccessDate := VarToDateTime(VBSpt.Eval('F.DateLastAccessed'));
ModifiyDate := VarToDateTime(VBSpt.Eval('F.DateLastModified'));
ASize := VBSpt.Eval('F.Size');
//形式を整えて表示
Memo1.Lines.Add(' ファイル名 : ' + AFileName);
Memo1.Lines.Add(' 種類 : ' + AType);
Memo1.Lines.Add(' 最終アクセス : ' +
FormatDateTime('yyyy年mm月dd日 hh時nn分', AccessDate));
Memo1.Lines.Add(' 最終変更 : ' +
FormatDateTime('yyyy年mm月dd日 hh時nn分', ModifiyDate));
Memo1.Lines.Add(' サイズ : ' + FormatFloat(',###.##0 KB', ASize/1024));
finally
FreeAndNil(SL);
FreeAndNil(VBSpt);
end;
Memo1.Lines.EndUpdate;
end;
end.
VBScript 内のコードの変数に値をセットするテストです。
まず、引数付きの関数を実行する場合の引数の与え方です。少し面倒ですが、VarArrayCreate 関数で配列を作成して SafeArray で渡します。外部のファイル内に値を設定するため、管理者権限 (管理者として実行) が必要となります。
もう 1 つの方法として、Button2Click では、VBScript のコードを読み込んで、そのコードに変数を設定するコードを追加してから実行しています。VBScript のコードは読み出しだけですから、管理者権限での実行は必要ありません。 |
 |
図14
設計時画面
- 任意のファイルを選択可能にするため TOpenDialog を使用
|
 |
図15
Button1 クリック
- TScriptControl の Run メソッドで実行
|
 |
図16
Button2 クリック
- 変数設定用のコードを追加して実行
- 上 3 行が追加したコード
|
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, MSScriptControl_TLB, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
Panel1: TPanel;
Button1: TButton;
OpenDialog1: TOpenDialog;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses ActiveX;
{$R *.dfm}
//=============================================================================
// 文字列を"(ダブルコーテーション)で囲んだ文字列を作成する関数
//=============================================================================
function AddQuotedStr(Str: String): String;
begin
Result := SysUtils.AnsiQuotedStr(Str, '"');
end;
//=============================================================================
// VBScript内の関数を実行
// Runメソッドを使用。関数の引数はVarArrayを使用してセット
//
// PSafeArrayの使用にはusesにActiveXが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
VBSpt : TScriptControl;
SL : TStringList;
Params : PSafeArray;
V : Variant;
AType : String;
begin
Memo1.Lines.BeginUpdate;
if OpenDialog1.InitialDir = '' then begin
OpenDialog1.InitialDir := ExtractFileDir(Application.ExeName);
end;
if OpenDialog1.Execute = False then exit;
//VBScriptオブジェクトを生成
VBSpt := TScriptControl.Create(Self);
VBSpt.Language := 'VBScript';
//VBScriptの関数に渡す値をセット
V := VarArrayCreate([0, 1], varVariant);
V[0] := ExtractFilePath(OpenDialog1.FileName);
V[1] := ExtractFileName(OpenDialog1.FileName);
Params := PSafeArray(TVarData(V).VArray);
//コードを格納するTStringList生成
SL := TStringList.Create;
try
//コードを読込む
SL.LoadFromFile(ExtractFilePath(Application.ExeName) + 'FilePropeties.txt');
//スクリプトにコードを追加
VBSpt.AddCode(SL.Text);
//VBSのコード内のFileTypeという関数を実行
//引数はParamsで渡す
AType := VBSpt.Run('FileType', Params);
Memo1.Text := SL.Text;
Memo1.Lines.Add('');
Memo1.Lines.Add(' ---------- 結果 ----------');
Memo1.Lines.Add('');
//結果を表示
Memo1.Lines.Add(' ファイル名 : ' + ExtractFileName(OpenDialog1.FileName));
Memo1.Lines.Add(' 種類 : ' + AType);
finally
FreeAndNil(SL);
FreeAndNil(VBSpt);
end;
Memo1.Lines.EndUpdate;
end;
//=============================================================================
// VBScript内の関数を実行
// コードの先頭に関数を呼出すコードと引数の値をセットするコードを追加して実行
// VBScript内に複数の関数がある場合は面倒
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
VBSpt : TScriptControl;
SL : TStringList;
begin
Memo1.Lines.BeginUpdate;
if OpenDialog1.InitialDir = '' then begin
OpenDialog1.InitialDir := ExtractFileDir(Application.ExeName);
end;
if OpenDialog1.Execute = False then exit;
//VBScriptオブジェクトを生成
VBSpt := TScriptControl.Create(Self);
VBSpt.Language := 'VBScript';
//コードを格納するTStringList生成
SL := TStringList.Create;
try
//コードを読込む
SL.LoadFromFile(ExtractFilePath(Application.ExeName) + 'FilePropeties.txt');
//変数に値をセットするためのコードを追加
SL.Insert(0, 'APath = ' + AddQuotedStr(ExtractFilePath(OpenDialog1.FileName)));
SL.Insert(1, 'AName = ' + AddQuotedStr(ExtractFileName(OpenDialog1.FileName)));
SL.Insert(2, 'RetStr = FileType(APath, AName)');
SL.Insert(3, '');
//スクリプトを実行
VBSpt.ExecuteStatement(SL.Text);
Memo1.Text := SL.Text;
Memo1.Lines.Add('');
Memo1.Lines.Add(' ---------- 結果 ----------');
Memo1.Lines.Add('');
//実行結果から値を取得
Memo1.Lines.Add(' ファイル名 : ' + ExtractFileName(OpenDialog1.FileName));
Memo1.Lines.Add(' 種類 : ' + VarToStr(VBSpt.Eval('RetStr')));
finally
FreeAndNil(SL);
FreeAndNil(VBSpt);
end;
Memo1.Lines.EndUpdate;
end;
end.
| TScriptContorl には OnError イベントがあります。その中で Error プロパティでエラー内容の文字列を取得できます。ここままでのサンプルでは、TScriptControl を実行時に生成していますが、このサンプルでは Form に配置してオブジェクト・インスペクタで OnError イベントを作成しています。 |
 |
図17
設計時画面
- TScriptControl コンポを配置してOnError イベントを作成
|
 |
図18
Button1クリック
|
リスト8
TScriptControl の OnError イベントを使う |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, MSScriptControl_TLB, StdCtrls, ExtCtrls, OleCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
Panel1: TPanel;
Button1: TButton;
ScriptControl1: TScriptControl;
procedure Button1Click(Sender: TObject);
procedure ScriptControl1Error(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
//=============================================================================
// ファイルからVBScriptのコードを読込んで実行
// 実行するのは表示コード部分のないVBSコード。表示はDelphiで実行
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
SL : TStringList;
AFileName : String;
AType : String;
ModifiyDate : TDateTime;
AccessDate : TDateTime;
ASize : Int64;
begin
ScriptControl1.Language := 'VBScript';
Memo1.Lines.BeginUpdate;
//コードを格納するTStringList生成
SL := TStringList.Create;
try
//コードを読込んで実行
SL.LoadFromFile('FilePropeties.txt');
try
Memo1.Text := SL.Text;
Memo1.Lines.Add('');
Memo1.Lines.Add(' ---------- 結果 ----------');
Memo1.Lines.Add('');
//スクリプト実行
ScriptControl1.ExecuteStatement(SL.Text);
//実行結果から値を取得
AFileName := VarToStr(ScriptControl1.Eval('F.Name'));
AType := VarToStr(ScriptControl1.Eval('F.Type'));
AccessDate := VarToDateTime(ScriptControl1.Eval('F.DateLastAccessed'));
ModifiyDate := VarToDateTime(ScriptControl1.Eval('F.DateLastModified'));
ASize := ScriptControl1.Eval('F.Size');
//形式を整えて表示
Memo1.Lines.Add(' ファイル名 : ' + AFileName);
Memo1.Lines.Add(' 種類 : ' + AType);
Memo1.Lines.Add(' 最終アクセス : ' +
FormatDateTime('yyyy年mm月dd日 hh時nn分', AccessDate));
Memo1.Lines.Add(' 最終変更 : ' +
FormatDateTime('yyyy年mm月dd日 hh時nn分', ModifiyDate));
Memo1.Lines.Add(' サイズ : ' + FormatFloat(',###.##0 KB', ASize/1024));
except
end;
finally
FreeAndNil(SL);
end;
Memo1.Lines.EndUpdate;
end;
//=============================================================================
// TScriptControlのOnErrorイベント
// エラーが発生しなければ何も表示しない
//=============================================================================
procedure TForm1.ScriptControl1Error(Sender: TObject);
begin
Memo1.Lines.Add(ScriptControl1.Error.Description);
Memo1.Lines.Add(ScriptControl1.Error.Source);
Memo1.Lines.Add(ScriptControl1.Error.Text);
end;
end.
マイクロソフトの以下の [Windows Script Version] というページからダウンロードできます。そこにある scd56jp.exe です (URL は 2010年08月20日現在)。
このヘルプファイルは 2001年と古く、ADVPACK.DLL もかなり古いバージョンですが、scd56jp.exe をインストールしても上書きはされないようです。不安であればヘルプファイルだけを取り出して利用するという手もあります。 |
 |
図19
scd56jp.exe の内容 |
 |
図20
VBScript のヘルプ |
| 08_JScript を使用した WSH のサンプルを Delphi で実行 |
WSH では JScript というスクリプト言語もよく使用されいます。ネット上にあるそのようなサンプルを Delphi で利用する時の参考です。
例えば次のコードはマイクロソフトが提供している音声合成エンジンを使用して、コンピュータが英語で Hello と発声します。このコードを TestVoice.js という名前で保存します。 |
リスト9
WSH (JScript) のコードの例 |
var tts = WScript.CreateObject("SAPI.SpVoice");
tts.Rate = 2;
tts.Speak("Hello!");
|
保存した拡張子が .js の JScript のコードは次のようにして実行できます。
拡張子 .js のファイルは JavaScript のファイルでもあります。そこで、JavaScript のファイルと区別するために明示的に WScript.exe を指定して実行しています。もし拡張子の関連付けが設定されていなければ ShellExecute 関数の第 3 引数を JScript のファイル名にすることができます。
WScript.exe の代わりに CScript.exe でも実行可能です。CScript.exe は、VBScript, JScript どちらのスクリプトも実行できます。
|
リスト10
保存した JScript (拡張子は .js) のファイルを実行
uses に ShellAPI が必要 |
//=============================================================================
// WSH(JScript)のファイルをDelphiで実行する例
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
ShellExecute(Handle,'', 'WScript.exe', 'TestVoice.js', nil, SW_HIDE);
end;
| 以下は、JScript のコードを Delphi のコードに変換して実行する例です。 |
リスト11
WSH (JScript) のコードを Delphi のコードに変換して実行
uses に ComObj が必要 |
//=============================================================================
// WSH(JScript)のコードをDelphiのコードに変換して実行
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
LSavedCW : Word;
LSpeach : OleVariant;
begin
//浮動小数点演算エラー回避
LSavedCW := Get8087CW;
Set8087CW(LSavedCW or $4);
LSpeach := CreateOleObject('SAPI.SpVoice');
LSpeach.Rate := 2;
LSpeach.Speak('Hello');
Set8087CW(LSavedCW);
end;
|
Windows の
SpVoice (SAPI) オブジェクトのの Speak メソッド
はデフォルトでは同期実行です。したがって、Speak メソッドが終了するまで Speak メソッドの次のコードは実行されません。
次のコードを使用すると、非同期に近い動作を実現できます。
|
リスト12
Windows SpVoice (SAPI) の Speak メソッドを非同期で実行 |
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
FObjSpeach : OleVariant;
FStopFlag : Boolean;
procedure SAPI_Speach(AText: string);
end;
var
Form1: TForm1;
implementation
uses
ComObj;
{$R *.dfm}
const
SVSFDefault = 0;
SVSFlagsAsync = 1;
SVSFPurgeBeforeSpeak = 2;
//=============================================================================
// SAPI.SpVoice オブジェクトを生成して音声を出力
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
LText : string;
begin
if not VarIsEmpty(FObjSpeach) then Exit;
Button1.Enabled := False;
LText := '1. 2. 3. 4. 5. 6. 7. 8. 9. 10';
SAPI_Speach(LText);
Button1.Enabled := True;
end;
//=============================================================================
// 音声出力を強制終了させるフラグをセット
// Stop メソッドの代用機能
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
begin
FStopFlag := True;
end;
//-----------------------------------------------------------------------------
// SAPI.SpVoice オブジェクトを生成して音声を出力
// 見かけ上非同期で動作させる例
// Stop 等の強制終了の方法がないのでオ終了まで待つ
//-----------------------------------------------------------------------------
procedure TForm1.SAPI_Speach(AText: string);
var
LSavedCW : Word;
begin
//浮動小数点演算エラー回避
LSavedCW := Get8087CW;
Set8087CW(LSavedCW or $4);
FStopFlag := False;
FObjSpeach := CreateOleObject('SAPI.SpVoice');
FObjSpeach.Rate := 2;
FObjSpeach.Speak(AText, SVSFlagsAsync);
repeat
Sleep(100);
if FStopFlag then Break;
Application.ProcessMessages;
until FObjSpeach.WaitUntilDone(10);
FObjSpeach := Unassigned;
Set8087CW(LSavedCW);
end;
end.
[備考]
本項のサンプルコードで使用している音声合成エンジンは、Windows 7 では日本語の読み上げはできません。Windows 8.1 / 10 であれば日本語も読み上げてくれます。
Windows 7 の場合は、Microsoft Speech Platform という、同じマイクロソフトが提供している音声合成エンジンを使用すると日本語も読み上げてくれます。
音声合成にはこの他にも多くの製品、ユーティリティ等があります。ジャストシステムの一太郎のプレミアム版以上には「詠太」という読み上げソフトが添付されています。
|
VBScript, JScript のバージョンは CScript コマンドを実行すると確認できます。このバージョンの値は WSH のバージョンと同じです。
下図は筆者の環境での値です。 |
 |
図21
Windows 7 |
 |
図22
Windows 10 |
|