呼び出し元の判別

解決


みに  2012-06-25 10:47:12  No: 42528  IP: 192.*.*.*

TForm1とTForm2からTForm_Selを呼び出したとします。
Tform_SelはTForm_Editを呼び出します。

このときTForm_EditはもともとTForm1から呼ばれたものかTForm2から呼ばれたものかをTForm_Edit内で判別する方法ありますか?
引数やグローバル変数等では判断せず、呼び出し元のクラス名?とかで判別したいです。

よろしくお願いします。

編集 削除
Mr.XRAY  2012-06-25 11:41:32  No: 42529  IP: 192.*.*.*

こんにちは.

あるフォームから,別の,他のフォームを「呼び出す」というのが,どんな動作を
意味するのか,よくわからないのですが.
どのように呼び出すのでしょうか?

編集 削除
通りすがり  2012-06-25 12:02:50  No: 42530  IP: 192.*.*.*

同じく「呼び出す」の意味がわからないのですが・・・

procedure TForm1.Button1Click(Sender: TObject);
var
  formsel: TForm_Sel;
begin
  formsel := TForm_Sel.Create(Self);
  formsel.ShowModal;
  formsel.Free;
end;

procedure TForm2.Button1Click(Sender: TObject);
var
  formsel: TForm_Sel;
begin
  formsel := TForm_Sel.Create(Self);
  formsel.ShowModal;
  formsel.Free;
end;

procedure TForm_Sel.Button1Click(Sender: TObject);
var
  formEdit:TForm_Edit;
begin
  formEdit := TForm_Edit.Create(Owner);  //Case.1
  //formEdit := TForm_Edit.Create(Self); //Case.2
  formEdit.ShowModal;
  formEdit.Free;
end;

procedure TForm_Edit.Button1Click(Sender: TObject);
begin
  ShowMessage(Owner.ClassName); //Case.1
  //ShowMessage(Owner.Owner.ClassName); //Case.2
end;

編集 削除
みに  2012-06-25 13:12:46  No: 42531  IP: 192.*.*.*

「呼び出す」とはShowModalです。

TForm1
TForm2
TForm_Sel
TForm_Edit

は全てApplication.CreateFormにて生成されたFormです。
この場合通りすがりさんのようにできませんよね?
このときはOwner.ClassNameとしてもTApplicationが返ってきてしまっていたので、困っていました。

現在このような状況です

編集 削除
take  2012-06-25 14:03:21  No: 42532  IP: 192.*.*.*

すでに生成済みの「Form_Edit」は「Form1」や「Form2」から
ShowModalにて呼び出されるが
「Form_Edit」側の処理で、「Form1」/「Form2」の
どちらから呼び出されたかが知りたい。
で、よろしいでしょうか?

クラス名で、しっかりと判定したいのであれば、
クラスの管理も「Application.CreateForm」ではなくて
自分でしないと・・・

クラスを管理しない場合、自分なら簡単にこんな感じで
クラス名に関係なく数値で管理しちゃいますけどね

// Form1から呼び出し
formSel.Tag := 1;
formSel.ShowModal;

// Form2から呼び出し
formSel.Tag := 2;
formSel.ShowModal;

TForm_SelからTForm_Editを呼ぶところで
formEdit.Tag := Tag;
formEdit.ShowModal;

// TForm_Edit側での判定
if (tag = 1) then begin
end;

編集 削除
Mr.XRAY  2012-06-25 16:44:20  No: 42533  IP: 192.*.*.*

例えば,以下のような方法もあります.参考までに.

>TForm_Selを呼び出したとします
TForm_Selを呼び出したとします   ---> TFrom_SelをShowModalで表示します.ですね.
具体的な用語を使用した方がいいですよね.皆様... (えっ!? 大きなお世話...? )
それと,環境を忘れずに(また,書いてしまった... 汗)


ShowModal を実行したフォームが非アクティブになることを利用した方法です.
Form1, Form2, Form3 を新規プロジェクトで作成します.

--------------------  Form1 --------------------
  メインフォームです.
  TButtonを2つと,TEditを配置し,Buttonのクリックを以下のようにします.
  
  procedure TForm1.Button1Click(Sender: TObject);
  begin
    Form2.ShowModal;
  end;

  procedure TForm1.Button2Click(Sender: TObject);
  begin
    Form3.ShowModal;
  end;  

--------------------  Form2 --------------------
  TButtonを1つと,TEditを配置し,Buttonのクリックを以下のようにします.
  
  procedure TForm1.Button1Click(Sender: TObject);
  begin
    Form3.ShowModal;
  end;

--------------------  Form3 --------------------
  何も配置しません.以下のコードにします.
  
unit Unit3;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm3 = class(TForm)
    Memo1: TMemo;
  private
    { Private 宣言 }
  protected
    procedure WMActivate(var Message: TWMActivate); message WM_ACTIVATE;
  public
    { Public 宣言 }

  end;

var
  Form3: TForm3;

implementation

uses Unit1, Unit2;

{$R *.dfm}

//=============================================================================
//  このフォームがアクティブになる時のWM_ACTIVATEメッセージ処理
//  このフォームがアクティブになる時に,非アクティブになるウィンドウを検出
//  検出可能なのは,このフォームが属するアプリのものに限る
//=============================================================================
procedure TForm3.WMActivate(var Message: TWMActivate);
var
  Control : TWinControl;
begin
  if Message.Active <> WA_INACTIVE then begin
    Control := FindControl(Message.ActiveWindow);
    //他のアプリから[Alt]+[TAB]でアクティブになる時はControl = nilとなる
    if Control <> nil then begin
      if Control.Name = 'Form1' then begin
        Form1.Edit1.Text := 'Form1 成功!!';
      end else
      if Control.Name = 'Form2' then begin
        Form2.Edit1.Text := 'Form2 成功!!';
      end;
    end;
  end;
end;

end.

動作確認環境は,質問された方と多分同じでしょう.

編集 削除
通りすがり  2012-06-25 18:19:23  No: 42534  IP: 192.*.*.*

んだば、全部自動生成で、Unit3がForm_Selのユニットの場合・・・

uses
  Unit1, Unit2, Unit3;

procedure TForm_Edit.Button1Click(Sender: TObject);
var
  nwh: THandle;
begin
  if Form1.Visible and Form2.Visible then begin
    nwh := GetNextWindow(Form_Sel.Handle, GW_HWNDNEXT);
    while (nwh <> 0) and
    (nwh <> Form1.Handle) and (nwh <> Form2.Handle) do begin
      nwh := GetNextWindow(nwh, GW_HWNDNEXT);
    end;
    if nwh = Form1.Handle then ShowMessage('Form1ですよ')
    else if nwh = Form2.Handle then ShowMessage('Form2ですよ');
  end
  else if Form1.Visible then ShowMessage('Form1ですよ')
  else if Form2.Visible then ShowMessage('Form2ですよ');
end;

編集 削除
Mr.XRAY  2012-06-25 20:26:32  No: 42535  IP: 192.*.*.*

スミマセン.間違えました.
私の提示したコードは,全く思い違いをしていました.

>TForm1とTForm2からTForm_Selを呼び出したとします。
>Tform_SelはTForm_Editを呼び出します。

TForm1またはTForm2で,
TForm_Sel.ShowModal;

TForm_Selで
TForm_Edit.ShowModal;

このとき,TForm_Selが,どのフォーム(TForm1またはTForm2)から表示されたか?
でしたね.つまり,2つ前の祖先ですね.
失礼しました.

編集 削除
KHE00221  2012-06-25 21:29:11  No: 42536  IP: 192.*.*.*

FormShow で  Application.ActiveFormHandle

編集 削除
Sara  2012-06-26 10:13:12  No: 42537  IP: 192.*.*.*

いろいろな方法があるものですね・・・(すごい)

わたしは、普段こんな感じです・・・
まぁローカル変数も使ってはいけないなら、お呼びじゃないですが・・・(^^;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;


procedure TForm1.Button1Click(Sender: TObject);
begin
   Form_Sel.Inst := Cardinal(Form1);
   Form_Sel.ShowModal;
end;


**************************************************

type
  TForm2 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;


procedure TForm2.Button1Click(Sender: TObject);
begin
   Form_Sel.Inst := Cardinal(Form2);
   Form_Sel.ShowModal;
end;

**************************************************

type
  TForm3 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
    Inst : Cardinal;
  end;



procedure TForm3.Button1Click(Sender: TObject);
begin
   Form_Edit.Inst := Inst;
   Form_Edit.ShowModal;
end;


**************************************************

type
  TForm_Edit = class(TForm)
    Edit1: TEdit;
    procedure FormShow(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
    Inst : Cardinal;
  end;


procedure TForm_Edit.FormShow(Sender: TObject);
begin
   Edit1.Text := TForm(Inst).Name;
end;

編集 削除
みに  2012-06-26 10:31:05  No: 42538  IP: 192.*.*.*

皆様ありがとうございます。

現在色々な方法で試しています。
私なりに判断ですが、最悪Tform_Selでどちらかから呼び出されたか判断できれば、あとは全てTform_SelでTForm_Editに処理をしてしまえばよいと思いました。
なぜグローバル変数を使いたくないかというとプログラマ自身が設定のし忘れ等で、TForm_Editが思わぬ表示や動作にならないようにしたいからです。

なので Tform_Selでハンドル等で判断できればもともとあるForm1,2は変数の設定を気にせずTform_Selを呼べるわけです。

そこで、通りすがりさんの
GetNextWindowをTform_Selで行いましたが、Form1,2のハンドルを取得できませんでした。↓
GetNextWindow(self.Handle, GW_HWNDNEXT);

TForm1はShowModalでTForm_Selを読んでいるのですが、この場合GetNextWindowは使えると思ったのですが...

また、KHE00221さんのActiveFormHandleはFormsに存在しませんので、使用できませんでした。(Delphi7です)

編集 削除
Nov  2012-06-26 14:22:09  No: 42539  IP: 192.*.*.*

>ActiveFormHandleはFormsに存在しませんので、

GetActiveWindowで代用できるかもです。

編集 削除
みに  2012-06-26 15:09:23  No: 42540  IP: 192.*.*.*

みなさん色々な意見ありがとうございました。
1つのことに対してこれだけアプローチの方法があるのだと勉強になりました。

やりたいことはGetActiveWindowでできましたので、解決とします。
ありがとうございます。

編集 削除