Formを引き数にして外部プロシージャを呼び出すには?

解決


VB.NETビギナー  2006-11-13 17:37:22  No: 134104

>管理人様
未解決の質問がある段階で新しい質問は受け付けられない場合には削除してください。

VB6ではForm自体プロシージャの引き数にすることができました。
そして引き数のForm上のコントロールにアクセスすることができました。

同様のことをVB.NETでやろうとするとうまく行きません。
何らかの方法があるのか、あるいは同様のことはできないのでしょうか?


特攻隊長まるるう  2006-11-14 04:55:52  No: 134105

[VB.NET]はオブジェクト指向の概念を取り入れた設計となって
います。
[@IT オブジェクト指向プログラミング超入門]
http://www.atmarkit.co.jp/fdotnet/basics/oop_index/index.html

あるクラス(Form)が所有しているオブジェクト(Control)を、何でもかんでも
外部に公開するのは悪い設計だとされています。
また、実際にそういった設計が足かせになるケースもあるようです。
http://blogs.wankuma.com/jeanne/archive/2005/02/02/12252.aspx

以上のような理由だと思うのですが、フォームに貼り付けたコントロールは、
デフォルトの設定ではプロジェクトの外部に公開されていません。ただし、
仕組みとしてはコントロールの参照変数が Friend で宣言されているだけ
です。従って、同じプロジェクト内なら参照できますし、自動で書かれる
宣言部を Public に書き換えれば公開する事も可能です。

しかし通常は、プロパティやメソッドを自作して、利用したい部分だけ外部に
公開します。
[VBレスキュー花ちゃん]Form1 からForm2 のテキストボックスの内容を読み書きする
http://hanatyan.sakura.ne.jp/dotnet/form09.htm
(http://hanatyan.sakura.ne.jp/index.html)


我龍院  2006-11-14 06:02:11  No: 134106

>VB6ではForm自体プロシージャの引き数にすることができました。
>そして引き数のForm上のコントロールにアクセスすることができました。
>同様のことをVB.NETでやろうとするとうまく行きません。
VB.NETの場合はForm1、Form2はクラス名です、従ってForm1を渡してもだめです。
Form2のインスタンスに渡すべきForm1のインスタンスの名前はMeです。
Form1にTextBoxを一つ置いて・・・

'Form1側
Public Class Form1
   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
       Dim F2 As New Form2
       F2.Setform1(Me)
   End Sub
End Class

'Form2側
Public Class Form2
    Private F1 As Form1
    Public Sub Setform1(ByVal Form1)
        F1 = Form1
        F1.TextBox1.Text = Me.Name
    End Sub
End Class


VB.NETビギナー  2006-11-14 19:17:12  No: 134107

>特攻隊長まるるう様、我龍院様
ありがとうございます。
帰ったら早速試してみます。


VB.NETビギナー  2006-11-15 13:54:23  No: 134108

みなさん、どうもありがとうございました。
うまく行きました。


VB.NETビギナー  2006-11-15 18:20:31  No: 134109

申し訳ありません。解決したと思ったら解決していませんでした。

特攻隊長まるるう様、我龍院様からご教示いただいた方法ですが、
これはひとつのFormから別のForm上のコントロールに対するアクセスでしたが
実際には複数のFormから特定の(ひとつの)Form上のコントロールにアクセス
する必要が生じてしまいました。

つまり、Form1やForm2、Form3などからForm4上のコントロールに
アクセスできないかというものです。
これは可能なのでしょうか?


特攻隊長まるるう  2006-11-16 04:46:31  No: 134110

>つまり、Form1やForm2、Form3などからForm4上のコントロールに
>アクセスできないかというものです。
…過去ログ検索『別フォーム』等を実行してもらえれば、色々な情報が
手に入るはずです。 ここの過去ログは豊富なので、思いつく限りの
キーワードで検索してみることをお勧めします。

〜3つの手法を紹介します。〜

1つ目の手法で、まず一番に考えるのは、フォーム同士の親子関係
です。

1つのウィンドウからポップアップするダイアログのように、
主となる親画面が、従となる子画面を複数表示する場合、
親画面が全ての子画面のインスタンスを管理するように
設計します。
>Form1やForm2、Form3などからForm4上のコントロールに
他の全てのフォームが Form4 に関連しているなら、逆の発想で
Form4 が Form1やForm2、Form3 を生成すれば解決するのでは?

全ての子フォームを管理するような親フォームが存在しない場合、
親クラスを作成して、そのクラスが全てのフォームを管理するように
します。オブジェクト指向を意識して、子フォームは親フォームの
存在を意識しないように考えています。(子はイベントを起こすだけで
親フォームに直接命令を出しません。フォームの上に乗ってるコントロール
のようなイメージです。)
http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200606/06060011.txt
子フォームが閉じないようにする処理も親クラスで管理しています。

2つ目。そうは言ってもオブジェクト指向を意識しすぎて複雑な
設計になってしまう場合もあるでしょう。

[VB.NET]でも[VB6.0]と同じような Module を使用できます。
http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200607/06070077.txt
グローバルな変数を用意するだけ。
でも、フォームが破棄された場合も考えて、工夫しないといけないでしょう。

2つ目を利用するくらいなら3つ目。
Shared で共有化されたプロパティで、フォームクラス1つにつき1つの
インスタンスを返すようにします。
(自動で書かれる Sub New() を Private に宣言すればフォームの New も
制限できます。)
[DOBON.NET .NET Tips]フォームが一つしか表示されないようにする
http://dobon.net/vb/dotnet/form/singleform.html
当然フォームを破棄したら別のインスタンスが返されます。
×ボタンなどで破棄されないようにするには、1つ目の手法でも使ってますが、
Closing イベントでキャンセルしてください。


特攻隊長まるるう  2006-11-16 04:55:05  No: 134111

ちなみに[VB6.0]でもOOPは実現できます。
http://jeanne.wankuma.com/tips/rule/vb6oop.html
.NETでも[VB2005]になると復活してるので対策を考えてる
ような記事もあったり。。。
http://blogs.wankuma.com/jeanne/archive/2006/10/26/42540.aspx


我龍院  2006-11-16 18:16:42  No: 134112

>VB6ではForm自体プロシージャの引き数にすることができました。
>そして引き数のForm上のコントロールにアクセスすることができました。
VB6ではForm上のコントロールに対して、どのFormからでもアクセス出来ましたが、
それにもかかわらず、なぜ上記のような方法を取るのか判らなければ、
適切なアドバイスは難しいですね。


VB.NETビギナー  2006-11-17 23:00:13  No: 134113

>特攻隊長まるるう様
書いていただいた内容に基づいて問題解決を図ってみます。
ありがとうございました。

>我龍院様
カプセル化ということでしょうか?
だとしたらカプセル化の意義そのものは理解できているつもりですが、
安全化(という言い方でいいのかどうか?)のためにどうしても制限が
生じてしまっているという理解で正解でしょうか?


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

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






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