つい最近まで実行中のアプリケーションやフォームのハンドルなどを取得するには、FindWindow API や EnumWindow API を使用してクラス名やタイトルで引っ掛けて取得するものだと思ってました。 しかし、OLEオブジェクトであれば VB が GetObject 関数でインスタンスを取得できるように、Delphi は GetActiveOleObject 関数でインスタンスを取得できます。(※1 Excel 2000 で GetObject を使用すると問題が発生することがあるようです。 詳細はここを参照してください。
http://support.microsoft.com/default.aspx?scid=http://www.microsoft.com/japan/support/kb/articles/JP413/9/00.asp)
GetActiveOleObject関数で外部アプリケーションにアクセスする
CreateOleObject関数は、外部アプリケーションの新しいインスタンスを作成する関数でした。 したがって、すでにアプリケーションが起動している状態でCreateObject関数を使うと、同一のアプリケーションが次々に起動してしまうことになります。
一方、GetObject関数は、すでに起動している外部アプリケーションにアクセスする関数になります。 したがって、GetObject関数を使えば、同一のアプリケーションが複数起動することはありません。
VB の GetObject関数は 2 つの引数をとりますが、Delphi の GetActiveOleObject はクラス名のみを引数にとります。
function GetActiveOleObject(const ClassName: string): IDispatch;
以下のサンプルでは、GetObject関数を使ってWordにアクセスしています。すでにWordが起動している場合はそのまま処理を続行しますが、未起動のときには EOleSysError のエラーが発生します。このエラーを検知したときには、CreateOleObject 関数で Word を起動しています。(※2 このサンプルプログラムを動作させるには、implementation 部に ComObj を追加する必要があります。)
procedure TForm1.Button1Click(Sender: TObject); var objWord: OleVariant; bAppOpen: Boolean; begin try objWord := GetActiveOleObject('Word.Application'); bAppOpen := true; except on E: EOleSysError do begin bAppOpen := false; end; end; // Wordのインスタンスが作成されていなかったら作成する if not bAppOpen then begin objWord := CreateOleObject('Word.Application'); // 新規文書を挿入する objWord.Visible := true; objWord.Documents.Add; end; objWord := Unassigned; end;