Releaseしたのに「Formが使われている」となる?


かなパパ  2008-05-18 20:35:59  No: 30722

Form2をReleaseした後でないと、再度Createできないはずなのに
「コンポーネント名 Form2 はすでに使われています」でエラーになります。
 
(1) アプリケーションがActiveになる時に、TCommXのオープンを行っています。
    (親となるシステムでもQRコードリーダーを使っている為)
(2) アプリケーションがDeActiveになる時に、TCommXのクローズを行っています。
(3) Form2はエラーが発生したプログラムと並行に実行可能なプログラムでも共有しています。
(4) TCommXのオープン、クローズを行わない場合はエラーが発生しない様です。
(5) エラーが発生する場合と発生しない場合があります。
    上記以外のエラーの発生する条件がわかっていません。
    また、エラーはプログラムの提供先でのみ発生しているのでエラーが発生しているタイミングもわかっていません。
 
エラーを回避する方法等、おわかりの方いらっしゃいましたら、ご教授お願いします。
以下がソース(サンプル)です。よろしくお願いします。
 
TFrom1 = class(TForm)
  //省略
  CommX1: TCommX;
  //省略
private
  //省略
  function ComPortOpen: Boolean;
public
  procedure ActivateProc(Sender: TObject);
  procedure DeActivateProc(Sender: TObject);
end;
//==============================================================================
// Form1
//==============================================================================
procedure TForm1.FormShow(Sender: TObject);
begin
  Application.onfiltered= ActivateProc;     //アプリがアクティブになった場合の処理
  Application.onfiltered= DeActivateProc;   //アプリがアクティブでなくなった場合の処理
  QRComFlg := True;  //QRを利用するかどうかの設定を持つのであれば、このフラグで切替え
  if not ComPortOpen then QRComFlg := False;
end;
//-----------------------------------------------------------
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  DeActivateProc(Self);
end;
//==============================================================================
// QR制御
//==============================================================================
procedure TForm1.ActivateProc(Sender: TObject);
begin
  if QRComFlg then
  begin
    try
      ComPortOpen;
    except
      QRComFlg := False;
    end;
  end;
end;
//----------------------------------------------------------
procedure TForm1.DeActivateProc(Sender: TObject);
begin
  if QRComFlg then
  begin
    CommX1.PortClose;
  end;
end;
//-----------------------------------------------------------
// QRポートオープン
//-----------------------------------------------------------
function TForm1.ComPortOpen: Boolean;
begin
  CommX1.ClearReceiveBuf;
  Result := True;
  CommX1.PortClose;
  try
    CommX1.PortNo    := //省略;
    CommX1.BitRate   := //省略;
    Commx1.CharSize  := //省略;
    Commx1.ParityBit := //省略;
    Commx1.StopBit   := //省略;
    Commx1.FlowCtrl  := //省略;
    CommX1.PortOpen;
  except
    Result := False;
  end;
end;
//==============================================================================
// Form2の表示
//==============================================================================
function TForm1.Button1Click(Sender: TObject)
begin
  //Button1クリック前のControlにSetFocus
  Button1.Enabled := False;
  Form2  := TForm2.Create(Application);
  try
    //省略
    Form2.ShowModal;
    //省略
  finally
    Form2.Release;
    Button1.Enabled := True;
  end;
end;


とおりすがり  2008-05-18 23:23:22  No: 30723

>  Application.onfiltered= ActivateProc;     //アプリがアクティブになった場合の処理
>  Application.onfiltered= DeActivateProc;   //アプリがアクティブでなくなった場合の処理

????同じイベントに代入してるし := でもないし?


そもそも  2008-05-19 04:54:18  No: 30724

Application に  OnFiltered なんてないでしょ?


KHE00221  2008-05-19 14:16:41  No: 30725

>(1) アプリケーションがActiveになる時に、TCommXのオープンを行っていま>す。
>    (親となるシステムでもQRコードリーダーを使っている為)

アプリが起動すれば自動的にActiveになるわけで、そしてアクティブになるとTCommX をオープンしているわけで

>(4) TCommXのオープン、クローズを行わない場合はエラーが発生しない様で>す。

TCommX のオープン、クローズを行わないときはどんなとき?

>(5) エラーが発生する場合と発生しない場合があります。
>    上記以外のエラーの発生する条件がわかっていません。
>    また、エラーはプログラムの提供先でのみ発生しているのでエラーが発>生しているタイミングもわかっていません。

サンプルにエラーの発生する箇所か書いてあるのか?


かなパパ  2008-05-19 18:24:38  No: 30726

多数のResありがとうございます。
  Application.onfiltered= ActivateProc;     //アプリがアクティブになった場合の処理
  Application.onfiltered= DeActivateProc;   //アプリがアクティブでなくなった場合の処理

  Application.OnActivate   := ActivateProc;     //アプリがアクティブになった場合の処理
  Application.OnDeActivate := DeActivateProc;   //アプリがアクティブでなくなった場合の処理
の誤りです。
どこで、記述がかわってしまったのか...

ウィンドウの切り替えで他アプリがアクティブになった時に、他アプリにQRコードリーダーを使わせない様にしています。


ttt  2008-05-19 19:35:02  No: 30727

Releaseしたのに云々と表題にあるので、とりあえずその周辺のコードでおかしいところ

>  Form2  := TForm2.Create(Application);
Form2というのはTForm2を宣言したunitにあるグローバル変数?
このグローバル変数はフォームの自動生成・管理のためにApplicationが使うものです。
(新規フォーム作成時にIDEが自動的に宣言を作りますが、自動生成にしないのなら消してしまってかまいません。というか消すべき)
これを使わずにローカル変数にしてみてください。

あと、Createの引数がApplicationというのも変。普通はSelf。

ちなみに「Form2はすでに使われています」というエラーは文字通り、
Nameプロパティの値が 'Form2' であるコンポーネントを二つ同時に
同一Owner内に作ろうとすると発生します。
質問の(3)で言っている共有というのが具体的に何をやっているのかわかりませんが、
Applicationをオーナーにしているので前に作ったFormへの参照が残っているのでは?

>    Form2.Release;
Releaseを使うのはForm2のイベント内で自分自身を解放する場合。
この場合はForm1のイベント内なのでFreeで十分です。


通りすがりの初心者  2008-06-08 21:01:29  No: 30728

私も同様の現象が発生しています。
私からも質問させて下さい。

OSの関数を使って、ApplicationをオーナーにしてCreateしたFormが解放されるまでWaitする方法はないのでしょうか?

かなパパさんと同じかどうかわかりませんが、当方では、
(1)プロジェクトファイルからForm2のCreateを削除し、自動生成にしない様にしています。
(2)Form2のユニットを他のプロジェクトでも使っています。もちろん、Form2を使った2つのApplicationは並行して実行可能にしています。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加