<p>つい最近まで実行中のアプリケーションやフォームのハンドルなどを取得するには、FindWindow API や EnumWindow API を使用してクラス名やタイトルで引っ掛けて取得するものだと思ってました。 しかし、OLEオブジェクトであれば VB が GetObject 関数でインスタンスを取得できるように、Delphi は GetActiveOleObject 関数でインスタンスを取得できます。(※1 Excel 2000 で GetObject を使用すると問題が発生することがあるようです。 詳細はここを参照してください。<br />
<a href="http://support.microsoft.com/default.aspx?scid=http://www.microsoft.com/japan/support/kb/articles/JP413/9/00.asp">http://support.microsoft.com/default.aspx?scid=http://www.microsoft.com/japan/support/kb/articles/JP413/9/00.asp</a>) <br />
<em>GetActiveOleObject関数で外部アプリケーションにアクセスする</em><br />
CreateOleObject関数は、外部アプリケーションの新しいインスタンスを作成する関数でした。 したがって、すでにアプリケーションが起動している状態でCreateObject関数を使うと、同一のアプリケーションが次々に起動してしまうことになります。<br />
　一方、GetObject関数は、すでに起動している外部アプリケーションにアクセスする関数になります。 したがって、GetObject関数を使えば、同一のアプリケーションが複数起動することはありません。<br />
VB の GetObject関数は 2 つの引数をとりますが、Delphi の GetActiveOleObject はクラス名のみを引数にとります。</p>
<pre class="brush: delphi">
function GetActiveOleObject(const ClassName: string): IDispatch;
</pre>
<p>以下のサンプルでは、GetObject関数を使ってWordにアクセスしています。すでにWordが起動している場合はそのまま処理を続行しますが、未起動のときには EOleSysError のエラーが発生します。このエラーを検知したときには、CreateOleObject 関数で Word を起動しています。（※2 このサンプルプログラムを動作させるには、implementation 部に ComObj を追加する必要があります。）</p>
<pre class="brush: delphi">
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;
</pre>