FAQ一覧へ インデックスへ

サブフォーム起動で二重起動防止し、さらに二重起動時にパラメーターを送


質問

サブフォーム起動で二重起動防止し、さらに二重起動時にパラメーターを送
るにはどうすればいいですか?



答え

 二重起動防止に、

>#22 七☆星 さん、[FAQ]Delphi2.0(Win32)での二重起動の防止

を使われていらっしゃる方、多いと思います。わたくしも大変重宝しており
ます。七☆星 さん、ありがとうございました。

 さて、二重起動を防止したときに、二重起動をファイルドロップなどで行
う場合、ここの方法は、旧モジュールのウインドウを見つけてフォーカスを
移す、ということですので、このパラメータ(ドロップファイル)は、アプ
リケーション間のデータ送信を行って、旧モジュールで受信してやる必要が
あります。

 (1) クリップボード
 (2) グローバルアトム
 (3) WM_COPYDATA メッセージ

が考えられます。(1) は簡単ですが、クリップボードを使いながら二重起動
してるとき、クリップボードのデータが勝手に変えられるのは好ましくない
かも知れません。(2)は、SBORLAND 旧 MES 9

>#21710 KHB05271  瑠瓏 さん、RE^3:二重起動防止時のハ゜ラメータ (96/12/18)

で紹介されていますが、ここでの、サブフォーム起動では、やり方が悪いの
か、うまく行かず、代わって、同じツリーの、

>#21698 GFC03235  HATENA さん、RE^2:二重起動防止時のハ゜ラメータ (96/12/17)

>    そこで、ここの過去のログを探してみると、#20072 で WM_COPYDATA 
>   についての記述を発見しました。これを使うとバッチリ文字列を渡すこ
>   とができました。
(改行位置変えました)

で成功しました。以下の例でそれを挙げます。


プロジェクトファイル:SubFirst.Prj
メインフォーム:      SubF1.Pas(フォーム名:SubFF1)
サブフォーム:        SubF2.Pas(フォーム名:SubFF2)

やりたいこと:
(1) 単体起動(こんな言い方でいいですか)、つまり単に実行ファイルやそ
のショートカットファイルをクリックして起動する場合はメインフォームを
表示。
(2) 二重起動防止
(3) ファイルをドロップして起動したとき、サブフォームを表示する。
(4) サブフォームが表示されているとき、ファイルドロップ起動すると、そ
のパラメータをサブフォームに渡してフォーカスする。

(i) プロジェクトファイル:SubFirst.Prj
>#22 七☆星 さん、[FAQ]Delphi2.0(Win32)での二重起動の防止
のコードを入れます。
 
begin
  (..略..)
  if hMutex <> 0 then begin
    (..略..)
    Wnd := FindWindow('TSubFF2', nil); {ここではサブフォーム}
    if Wnd<>0 then begin
      if ParamCount>0 then      {ドロップ二重起動}
        iShow:=2;               {グローバル変数のセット}
      (..略..)
      SetForegroundWindow(Wnd); {前面に移動してアクティフ゛化}
      if ParamCount>0 then 
        CopyDataToOld(Wnd,iShow,ParamCount);
                                {旧モジュールにパラメータ送信}
      (..略..)
    end;
    {ミューテックスを閉じる}
    CloseHandle(hMutex);
  end else begin
    {以下は通常通りの処理を行う}
    Application.Initialize;
    Application.CreateForm(TSubFF1, SubFF1);
    Application.CreateForm(TSubFF2, SubFF2);
    iShow:=0;
    if ParamCount>0 then begin            {ドロップ起動}
      Application.ShowMainForm:=false;    {メインフォーム非表示}
      iShow:=1;                           {グローバル変数セット}
    end;
    Application.Run;
  end;
end.

(ii) メインフォーム:SubF1.Pas(フォーム名:SubFF1)
 設計時 Visible=false など

>[FAQ]起動直後にサブフォームを開きたい

のコードを入れます。

(ii) サブフォーム:SubF2.Pas(フォーム名:SubFF2)
procedure TSubFF2.AppMessage(var Msg: TMsg; var Handled: Boolean);
begin
  if (GetForeGroundWindow=SubFF2.Handle) then 
    if (iShow=1) then begin
      {..処理..}
    end;
end.

など、ドロップ起動時のコードを、
>[FAQ]起動直後にサブフォームを開きたい
にならって入れます。

 次に、ドロップでの二重起動時のデータ受信ですが、
  private
    { Private 宣言 }
    procedure WMCopyData(var Msg: TWMCopyData); message WM_COPYDATA;
を使います。
 データは、
    PChar(Msg.CopyDataStruct^.lpData)
に入ってきます。

 データ送信、(i)の CopyDataToOld(Wnd,iShow,ParamCount); は、

  acData: array[0..255] of char;

に送りたいデータを入れて、

  CDS.cbData:=SizeOf(acData);
  CDS.lpData:=@acData;
  SendMessage(Wnd,WM_COPYDATA,0,LongInt(@CDS));
             {Wnd はサブフォームのウィンドウハンドル}

で送信できます。