関数を別Formでも使用するには

解決


りんご  2004-05-13 05:49:21  No: 8921

自分なりに試したのですがうまくいきません。
ご存知の方がおりましたら、教えてください。

FormAとFormBはほぼ同じような画面です。
(ワケがあって、別々にしなくてはいけません。)

FormAで自作した関数をFormBで呼び出して使用したいのですが、
うまくいきません。
原因は、FormBでFormAの関数を呼び出してもFormBと判断してもらえず、
FormAで処理しているためということまではわかりました。

どうすれば、FormAとFormBで同じ処理をする関数を作成することが
できますか?

よろしくお願い致します。


にしの  2004-05-13 06:23:25  No: 8922

FormBからFormAの関数を呼び出すところはできているのでしょうか。
FormBにある関数を呼んでしまっているのでしょうか。

前者であれば、FormAにある関数の中で、FormAのメンバを直接操作していませんか?関数の中からFormAのメンバを直接操作せず、FormAのインスタンスを引数に渡して、そのインスタンスから操作するようにしておけば、FormBから呼び出してもOKです。

たとえば、

function TFormA.GetMemoText: String;
begin
  Result := Memo1.Lines.Text; // フォームに張ってあるMemo1からテキストを取得
end;

と会った場合、FormBから呼び出しても「FormAのMemo1からテキストを取得」ということになります。

function TFormA.GetMemoText(Sender: TForm): String;
begin
  if Sender Is TFormA then
    Result := (Sender As TFormA).Memo1.Lintes.Text
  else if Sender Is TFormB then
    Result := (Sender As TFormB).Memo1.Lines.Text;
end;
とすれば、SenderがFormAの場合FormAのMemo1から取得するし、SenderがTFormBであれば、FormBのMemo1から取得します。

後者であれば、FormA.FuncNameというように、「FormAの」関数を呼び出してください。


るるとん@K  2004-05-13 07:44:37  No: 8923

FormA:TFormAとして
FormA.FuncName();というふうに
FormAの関数を呼び出せば、関数内のSelfはインスタンスFormAを指します


りんご  2004-05-13 19:30:02  No: 8924

にしの様、るるとん@k様、解答ありがとうございました。

にしの様のアドバイス通りにやったところ、
思っていたように動いてくれました。

ですが、にしの様のアドバイス通りでいくと
フォームの数だけ、if〜else文が増えてしまいますよね?

function TFormA.GetMemoText(Sender: TForm): String;
begin
  if Sender Is TFormA then
    Result := (Sender As TFormA).Memo1.Lintes.Text
              ^^^^^^^^^^^^^^^^^^^
                        ↑
  ココの部分を何とか変数に持たせて、処理することって
  不可能なのでしょうか?

  私なりに、TForm型やObjectなどの変数に入れたりして
  試しているのですが、ダメでした。
  何か方法がありましたら、アドバイスよろしくお願い致します。


つっか  2004-05-13 19:48:07  No: 8925

TForm には Memo1 なんていうフィールドはないからね。その例で特定の
Memo1 にアクセスしたいなら TMemo型 の変数を渡したらいいんじゃないの。


にしの  2004-05-13 19:59:46  No: 8926

Interfaceを利用しましょう。

たとえば、
  IForm=interface
    function GetMemo: TMemo;
  end;
というinterfaceを用意して、

TFormA=class(TForm)
を、
TFormA=class(TForm,IForm)
に、

TFormB=class(TForm)
を、
TFormB=class(TForm,IForm)
に、それぞれ変更します。

TFormA,TFormBのそれぞれに、
procedure GetMemo: TMemo;
を実装してやれば、先のコードは、

function TFormA.GetMemoText(Sender: IForm): String;
begin
  Result := Sender.GetMemo.Lines.Text
end;

というようになります。


にしの  2004-05-13 20:02:17  No: 8927

ちょっと補足。
クラスの変数はできるだけpublicにせず、必要であればpropertyをpublicにして公開したほうがよいです。
人によってやり方はありますので、絶対とはいえませんが。


つっか  2004-05-13 20:35:36  No: 8928

それだと

> フォームの数だけ、if〜else文が増えてしまいますよね?

は解決しますが、フォームすべてにインタフェースを継承させる必要があって、
なんだか本末転倒ではありませんか?  Caller に依存した特定の Memo1 に
アクセスしたいなら、たんに TMemo 型の変数を渡すだけではないでしょうか。

> クラスの変数はできるだけpublicにせず、必要であればpropertyをpublicにして公開したほうがよいです。

一般論はそうですけど、フォームデザイナでポトペタした Memo1 なんかは
published ではないでしょうか。


にしの  2004-05-13 21:30:24  No: 8929

> フォームすべてにインタフェースを継承させる必要があって、
> なんだか本末転倒ではありませんか?  Caller に依存した特定の Memo1 に
> アクセスしたいなら、たんに TMemo 型の変数を渡すだけではないでしょう> か。
そういえば、型変換でできるかも。

  TFormEx=class(TForm)
  public
    Memo1: TMemo;
  end;
という定義を用意しておいて、

function TForm1.GetMemoText(Sender: TForm): String;
var
  Form: TFormEx;
begin
  Form := TFormEx(Sender);
  Result := Form.Memo1.Text;
end;

とすればもっと簡単にとれますね。

> 一般論はそうですけど、フォームデザイナでポトペタした Memo1 なんかは
> published ではないでしょうか。

「したほうがよい」であって「すべき」という意味で書いたわけではありません。
ですから、
> 人によってやり方はありますので、絶対とはいえませんが。
と書きました。

上に書いたTFormExでも変数をpublicにしてますし^^;


つっか  2004-05-13 22:15:32  No: 8930

> 上に書いたTFormExでも変数をpublicにしてますし^^;

上の方式では、他のユニットから Memo1 フィールドにアクセスする必要があるの
で、public 以上の可視性にする必要がありますよね。一方、

function TFormA.GetMemoText(Memo:TMemo): String;
begin
  Result := Memo.Lines.Text
end;

のように、TMemo 型の変数を渡す場合は、Caller の方で見えていればいいので
どの可視性でもいいわけです。この場合は、Caller が属している TForm 派生
クラスの private であってもかまいません。参照が直接渡されるからです。


にしの  2004-05-13 23:01:32  No: 8931

私は、投稿者の意図するところが、「それぞれのフォームを指定して、同じ関数で処理する」と思って書いています。
「それぞれのTMemoを指定して」であれば、つっかさんのおっしゃるとおりです。
TMemoを持ち出したのは私で、単なる例ですので。
確かに、各フォームのTMemoだけであれば、それぞれTMemoのインスタンスから取得すればよいはずですから、つっかさんの書いたようなコードになります。


るるとん@K  2004-05-14 01:22:52  No: 8932

フォームのクラス名は文字列ですから、caseも可能です
しかしインターフェイスを実装するのが妥当かと思われます
AとBが同じクラスにすることが出来れば、それが一番良いのですが


るるとん@K  2004-05-14 01:30:23  No: 8933

ぁ、文字列は比較できませんでした


にしの  2004-05-14 01:31:03  No: 8934

文字列はcase ofで使用できません。
使用できるのは順序型です。


りんご  2004-05-14 17:57:28  No: 8935

みなさん、たくさんのアドバイスありがとうございました。
おかげで、解決することができました。
私が知らないことがまだまだあるのだと思い、
もっと勉強しなくてはと思いました。
本当にありがとうございます。
感謝してます。


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

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






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