DOBON.NET DOBON.NETプログラミング掲示板過去ログ

自作クラス内からFormのオブジェクトを参照したい

環境/言語:[VB.NET 2003]
分類:[.NET]

おはようございます。
このサイトに、いつもお世話になっています。
今日は質問したいことがあり、新しくスレッド作成させていただきました。

今回の質問とは、簡単に言うと、
『自分で作ったプロジェクト内のクラスから、
フォームに設置してあるオブジェクトのプロパティを参照できますか?』
です。

http://dobon.net/vb/dotnet/form/accessanotherformdata.html
を参考に試行錯誤してみたのですが、どうやら少し違うようです。

ラジオボタンやテキストボックスの値をクラス内で取得、使用したいのですが、
その実現方法のイメージすら沸きません^^;

Form1内の変数をForm2で参照・・・というのは多々見かけたのですが、
クラスからの参照、また、オブジェクトのプロパティを・・となると
探し出すことができませんでした。

解決に役立つヒントやサイト等を教えていただきたくて書き込みしました。
よろしくお願いします_(._.)_
こんにちは、じゃんぬねっと です。

■No8376に返信(あのねさんの記事)
> Form1内の変数をForm2で参照・・・というのは多々見かけたのですが、
> クラスからの参照、また、オブジェクトのプロパティを・・となると
> 探し出すことができませんでした。

同じことだと思います。
ただ、あなたが良く見るサンプルは、ローカルスコープでやっているだけです。
参照したフォームのインスタンスは同一でなければなりませんので、
Friend などで公開するだけかと。(プロパティも)



   /*******************************************
     * @Homepage  http://f57.aaa.livedoor.jp/~jeanne/
     * @Blog        http://www.ailight.jp/blog/jeanne/
     *******************************************/
2005/01/13(Thu) 11:44:04 編集(投稿者)

お早いお返事、ありがとうございます。

・・・が、すみません・・・。
私の勉強不足故、イマイチ理解しきれませんでした^^;

>Friend などで公開するだけかと。(プロパティも)
Form1のTextBox1.Textプロパティを参照したい・・・と思ったら、
そ上のオブジェクト(Text1)のModifiersプロパティを"Friend"にする・・
といった感じではないのでしょうか?


Public Class clsTest
Public Function funTest() As Boolean
Dim main As New Form1
MsgBox(main.TextBox1.Text)
End Function
End Class

としてみたところ、メッセージボックスは表示されますが、
Newされている為か、TextBox1のデフォルトの値が出力されてしまいました^^;
(変更後のTextが表示されない)
こんにちは、じゃんぬねっと です。

■No8379に返信(あのねさんの記事)
> Newされている為か、TextBox1のデフォルトの値が出力されてしまいました^^;
> (変更後のTextが表示されない)

それは、先にも言ったように、同一インスタンスでないからですね。

> Form1のTextBox1.Textプロパティを参照したい・・・と思ったら、
> そ上のオブジェクト(Text1)のModifiersプロパティを"Friend"にする・・
> といった感じではないのでしょうか?

VB.NET ではデフォルトで Friend ですが、本来は Private にすべきでしょうね。
フォームもクラスであると考えれば、当然、プロパティでアクセスすべきでしょう。
何が、外部から参照されているかを明示化できるので、後から見てもわかりやすいです。

が、まあ、そういう固いのは抜きにして、まず解決させちゃいましょうか。
コードで説明した方がわかりやすいですね。

例えば、フォームが FormMain として、
あるモジュール [またはクラス] で、Friend メンバとして公開します。

※[ ] 内の記述は「Main」が Class である場合

Source:-------------------------------------------------

' Main モジュール [クラス]
Friend Module [Class] Main
    Friend fFormMain As FormMain

    ' エントリ ポイント から FormMain を起動
    Friend [Shared] Sub Main()
        fFormMain = New FormMain
        Application.Run(fFormMain)
    End Sub

End Module [Class]

Source:-------------------------------------------------

' テスト用の Moo クラス
Public Class Moo

    ' ちょっとだけ fFormMain の Text を表示するメソッド
    Private Sub ChottoDakeNoMethod()
        MessageBox.Show(fFormMain.TextBox1.Text)
        '[ MessageBox.Show(Main.fFormMain.TextBox1.Text) ]
    End Sub

End Class

--------------------------------------------------------

これが 1 番簡単な方法だと思いますが、
クラスの関係 (仕様上の) が気になるようになると、
これで納得できないようになると思います (w



 /***************************************************
  * @Remarks     じゃんぬねっと
  * @Homepage    http://f57.aaa.livedoor.jp/~jeanne/
  * @Blog        http://www.ailight.jp/blog/jeanne/
  ***************************************************/
じゃんぬねっとさん、ありがとうございます。

教えていただいた方法で、とりあえず動くところまでいきました。
無事に動いたのはいいのですが、どうしてこれで正常に動くのかが
イマイチ掴みきれませんでした。

下の画像のような処理をしたい為、現在、下記のコードで動かしています。


↓ここから ---------------------------------------------------------------

 '- 新しく作ったモジュール -----------------------
 Friend Module modHoge
  Friend fFormMain As frmMain

  Friend Sub Main()
   fFormMain = New frmMain
  End Sub
 End Module
 '------------------------------------------------

 '- Form1 (図:左上) -----------------------------
 Public Class Form1
  Private Sub Button1_Click (略
   fFormMain = New frmMain
   fFormMain.ShowDialog(Me)
  End Sub
 End Class
 '------------------------------------------------

 '- frmMain (図:右側) ---------------------------
 Public Class frmMain
  Private Sub btnHyoji (略
   clsTest.hyoji()
  End Sub
 End Class
 '------------------------------------------------

 '- clsTest --------------------------------------
 Public Class
  Public Function hyoji (略
   MsgBox(fFormMain.TextBox1.Text)
  End Function
 End Class
 '------------------------------------------------

↑ここまで ---------------------------------------------------------------


わざわざForm1を用意してあるのは、frmMainは、他の方が作成している
Formから呼び出される形になる為です。

この時、[modHoge]はどのタイミングで呼ばれているのでしょうか?
(ブレークポイント設定して動かしても引っかからなくて^^;)
また、モジュールとクラスの使いどころの違いとはどのような
部分なのでしょうか?
(こういう場合はモジュールを使った方ががいいよ、とか)

何度も申し訳ありませんが、よろしくお願いします_(._.)_
(この記事にはファイル"hoge.JPG"が添付されていましたが、削除されました。)
こんにちは、じゃんぬねっと です。

■No8391に返信(あのねさんの記事)
> 教えていただいた方法で、とりあえず動くところまでいきました。
> 無事に動いたのはいいのですが、どうしてこれで正常に動くのかが
> イマイチ掴みきれませんでした。

うーむ...。(^-^A)

> Friend Module modHoge
>   Friend fFormMain As frmMain
>
>   Friend Sub Main()
>     fFormMain = New frmMain
>   End Sub
> End Module

と、

> この時、[modHoge]はどのタイミングで呼ばれているのでしょうか?
> (ブレークポイント設定して動かしても引っかからなくて^^;)

を見るに、エントリ ポイントが何たるかをご存知ないのでしょうか?
もし、ご存知ないのでしたら、Google などを使って検索しちゃってください。
その辺りさえ理解できれば、解決しそうな気がします。

> また、モジュールとクラスの使いどころの違いとはどのような
> 部分なのでしょうか?
> (こういう場合はモジュールを使った方ががいいよ、とか)

汎用的で、機能的にどこにも属さない関数は、標準モジュールで実装する。
汎用的で、機能的にはどこかに属すことができる関数は Static だらけなクラスに実装する。
ある役割を果たす一連の機能と動作は、クラス (非Static) に実装する。
って感じでしょうか。(うーん、日本語って難しい...)

# 基本的に、私は標準モジュールが嫌いな人間です。(C# ラブなので)

> 下の画像のような処理をしたい為、現在、下記のコードで動かしています。

画像まで用意しちゃうとは、すごい向上心ですね。
私も見習いたいと思います。(^-^*)



   /*******************************************
     * @Remarks    じゃんぬねっと
     * @Homepage  http://f57.aaa.livedoor.jp/~jeanne/
     * @Blog        http://www.ailight.jp/blog/jeanne/
     *******************************************/
じゃんぬねっとさん、ありがとうございます_(._.)_

あちこち見てみた結果、
 エントリポイント = 一番最初に呼び出される部分で、Main()という名前。
            → Main って名前をつけておいたら、そこを最初に
              処理してくれる。
・・・という事なのかな?と感じました。

もしかして、
>' エントリ ポイント から FormMain を起動
というのは、
『エントリポイントから起動 "される"』
のではなく、
『エントリポイントから起動 "させてね"』
の意味だったのでしょうか・・・?


frmMain内に、
 ↓------------------------------------------
  'これがエントリポイント??
  Friend Sub Main()
   Dim clsSubMain As New clsSubMain
   clsSubMain.Main()
  End Sub
 ↑------------------------------------------
 
を追加して、modHogeから処理部分を削除し、新しく作成したクラスの

 ↓------------------------------------------
  Public Class clsSubMain
   Friend Sub Main()
    fFormMain = New frmMain
    Application.Run(fFormMain)
   End Sub
  End Class
 ↑------------------------------------------

を呼び出してみました・・・(汗
動き自体に変化がないので、合っているのか間違っているのかすら(-"-;)


色々と悩みながら書いたので、文・考えがまとまっていないかもしれませんが、
よろしくお願いします_(._.)_
こんにちは、じゃんぬねっと です。
説明が下手で申し訳ないです m(_ _)m

■No8394に返信(あのねさんの記事)
> frmMain内に、
>  ↓------------------------------------------
>   'これがエントリポイント??
>   Friend Sub Main()
>    Dim clsSubMain As New clsSubMain
>    clsSubMain.Main()
>   End Sub
>  ↑------------------------------------------
>  ↓------------------------------------------
>   Public Class clsSubMain
>    Friend Sub Main()
>     fFormMain = New frmMain
>     Application.Run(fFormMain)
>    End Sub
>   End Class
>  ↑------------------------------------------

標準モジュール以外では、Shared を付けて Static メソッド (共有メソッド) にしてください。
(標準モジュール以外はクラスですから、フォームもクラスです)

この辺りも、本当は調べて頂きたかったです。
先の投稿で、

> ※[ ] 内の記述は「Main」が Class である場合

と記述した部分はこれに当たります。

> 動き自体に変化がないので、合っているのか間違っているのかすら(-"-;)

そもそも、エントリポイントから動いてますかね?
スタートアップの設定を以下のように変えてみてください。

 ・[プロジェクト (&P)] メニュー の 1 番下の [xxxx のプロパティ] を選択します。
 ・[xxxx プロパティ ページ] ダイアログの [共通プロパティ] ペインから「全般」を選択します。
  (というか、初めて見たのならば、初めから選択されているハズ)
 ・[スタートアップの設定 (&S)] を、「Sub Main」または、エントリポイントがある標準モジュールか、クラスを選択します。
 ・[OK] を選択して [xxxx プロパティ ページ] ダイアログを閉じます。

※ 「xxxx」にはプロジェクト名が入ります。



   /*******************************************
     * @Remarks    じゃんぬねっと
     * @Homepage  http://f57.aaa.livedoor.jp/~jeanne/
     * @Blog        http://www.ailight.jp/blog/jeanne/
     *******************************************/
何度もありがとうございます。

>そもそも、エントリポイントから動いてますかね?
この設定自体は、いつもやっているので分かります。
今回、私が作成しているものの場合は、
『Form1からfrmMainを呼び出す』
ので、Form1に設定しないといけないのだと思っていました。

というのも、この一覧に、自作したクラス名が表示されたことが
今までに1度もなかったからです。
(その必要もなかったので、気にも留めず・・・)

教えていただいたとおり、
 ------------------------------------
 Public Class clsSubMain
  Shared Sub Main()
   (略)
 ------------------------------------
に変更したら、表示されましたΣ(゚□゚*)

ここが解決したら、一気にぱーっと今までの部分が納得できた気がします。
(まだ間違えてたらどうしよう(汗))


結局、こうなりました。

↓ここから -------------------------------------------------------------

 '------------------------------------------
 'このクラスをエントリポイントに設定する
 
 Public Class clsSubMain
  Shared Sub Main()        ← Shared(`・ω・´)
   fFormMain = New frmMain
   fForm = New Form1       ← 追加

   Application.Run(fForm)    ← 引数変えた
   End Sub
 End Class
 '------------------------------------------

 '------------------------------------------
 Public Class Form1        ← frmMainのNew消した
  Private Sub Button1_Click (略
   fFormMain.ShowDialog(Me)
  End Sub
 End Class
 '------------------------------------------------

 '- clsTest --------------------------------------
 Public Class
  Public Function hyoji (略
   MsgBox(fFormMain.TextBox1.Text)
  End Function
 End Class
 '------------------------------------------------

↑ここまで -------------------------------------------------------------


今度こそ・・・大丈夫かな?(´・ω・`)
懇切丁寧に教えていただき、本当にありがとうございます。

解釈違いなんかがあったら、指摘よろしくお願いします_(._.)_
こんにちは、じゃんぬねっと です。

■No8401に返信(あのねさんの記事)
> この設定自体は、いつもやっているので分かります。
> 今回、私が作成しているものの場合は、
> 『Form1からfrmMainを呼び出す』
> ので、Form1に設定しないといけないのだと思っていました。

確かに、完成しちゃった時点では関係なくなるでしょうが、
エントリポイントがないと、あなたが担当されているモジュールの単体テストができませんよね?

# ただし、Form1 も 同一プロジェクト内になる場合はこの限りではありません。
# ん? 今回はこの限りになってるのかな?

> ここが解決したら、一気にぱーっと今までの部分が納得できた気がします。
> (まだ間違えてたらどうしよう(汗))

いや、多分大丈夫でしょう。
先にも書いたように、今後、この実装方法がイヤになってくると思いますよ。
その頃には、ご自分で解決するようになってることと思います。

> 解釈違いなんかがあったら、指摘よろしくお願いします_(._.)_

間違いはないと思いますが、アクセス修飾詞はちゃんと明示化しときましょ。

 「Shared Sub」→ 「Public | [Friend] Shared Sub」 などにしましょう。

省略していい (省略しなきゃいけない) のは、インターフェイスの内部定義と、
静的クラスのコンストラクタ、デストラクタくらいかな。



   /*******************************************
     * @Remarks    じゃんぬねっと
     * @Homepage  http://f57.aaa.livedoor.jp/~jeanne/
     * @Blog        http://www.ailight.jp/blog/jeanne/
     *******************************************/
2005/01/14(Fri) 13:17:02 編集(投稿者)

お返事、遅くなってしまいすみません。

丁寧に教えていただいたおかげで、何とか解決につながることが
できました。

ありがとうございました_(._.)_

またの機会も、よろしくお願いします('-'*)
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板