.NETで外部フォームで変数の呼び出し。

解決


入門者さん  2003-03-06 22:11:55  No: 106207

こんにちわ。
過去ログ「form1とform2の変数」というところを参考にVB.NETで試してみましたが、「form1のメンバではありません。」というエラーになりました。
VB.NETではやり方が変わるのでしょうか?

form2でTextBoxに入力した値を変数に入れて、form1がアクティブになったときにその変数をform1のTextBoxに入れる。
といった処理をしたいのですが、うまくできません。

====================================================================
(form1)
'form1がアクティブなったときの処理
Private Sub KSmst03_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Activated
    Dim Code As Integer
    Code = form2.TCode    'この部分にエラーが出る。
    TextBox1.Text = Code
End Sub
--------------------------------------------------------------------
(form2)
'グローバル領域で変数を宣言
Private TCode As Integer
'ボタンクリックされたときの処理
Private Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
    TCode = TextBox1.Text    'TextBox1に入力された値をTCodeに格納
    Me.DialogResult = DialogResult.OK    'form2を閉じる。
End Sub
====================================================================

以上のコードを作ったのですが、問題箇所があればご指摘・ご指導頂きたいです。
よろしくおねがいします。


nanashi  2003-03-06 22:55:16  No: 106208

変数がPrivateで宣言されているからじゃないッスか?
Publicに変更してみてください。


入門者さん  2003-03-06 23:02:17  No: 106209

あ。。。すいません。
コードの記述ミスです。
変数宣言はもちろんPublicです。
が、form1の方ではエラーをなってしまうのです。
form2のコードには問題ないと思うのですが・・・。


nanashi  2003-03-07 00:42:56  No: 106210

私の環境では全く問題なく動きます。

確認して欲しいんですが、
  1.TCodeは本当にDeclarations領域で宣言されているか。
  2.本当にform1からform2を参照することが出来るのか。

特に2は重要です。
VB.NETではVB6のように暗黙の了解でFormオブジェクトがGrobal宣言されていません。
form1内でform2を参照できるようにオブジェクト宣言するか、
標準モジュール内でform2をパブリックで宣言するか。

よく分からない場合はform2をロード、表示している辺りのソースを掲示してください。


入門者さん  2003-03-07 01:20:55  No: 106211

nanashiさん、どうもありがとうございます。
確認しなおしましたが、「1」については問題ありません。
「2」についてですが、ひょっとしたら自分の思ってることと違うのかも・・・。
まず、フォームの作り方なんですがform1でTextBoxとボタンを配置したあとに「プロジェクト>Windowsフォームの追加」で新規に同一プロジェクト内にform2を作りました。
で、form1からform2を表示する方法としては
=====================================================================
(form1)
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim listDialog As New form2()
    listDialog.ShowDialog()
    Me.DialogResult = DialogResult.OK
End Sub
=====================================================================
といった感じにボタンをクリックするとform2が開かれるようにしているんですが・・・。


nanashi  2003-03-07 02:31:34  No: 106212

思ってたとおりです。これですね、原因は。
簡単に説明しますと、スコープの問題です。

Button1_Click内でlistDialogというform2オブジェクトを宣言していますね。
で、listDialogというオブジェクトをShowDialogしています。
つまり入門者さんがform2だと思っているオブジェクトは
実際にはlistDialogというオブジェクトなんです。
で、このオブジェクトはButton1_Click内で宣言されているため、
このイベント内からしか扱えないという事です。
(分かり難いかもしれませんが、そういうことです。)

これを回避するにはlistDialogというオブジェクトをDeclarations内で宣言するか、
もしくは標準モジュール内でPublic宣言する必要があります。
そして扱う時は
    listDialog.TCode
のようにします。

====================================================================
(form1)
'グローバル領域で変数を宣言
Private listDialog as form2

'form1がアクティブなったときの処理
Private Sub KSmst03_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Activated
    Dim Code As Integer
    Code = listDialog.TCode
    TextBox1.Text = Code
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    listDialog = New form2()
    listDialog.ShowDialog()
    Me.DialogResult = DialogResult.OK
End Sub
--------------------------------------------------------------------
(form2)
'グローバル領域で変数を宣言
Public TCode As Integer
'ボタンクリックされたときの処理
Private Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
    TCode = TextBox1.Text    'TextBox1に入力された値をTCodeに格納
    Me.DialogResult = DialogResult.OK    'form2を閉じる。
End Sub
====================================================================

動作確認はしてませんが、こんな感じでしょうか。

あと、VB.NETをやる上でクラスの概念は必須だと思うので
クラスについて勉強することをオススメします。


入門者さん  2003-03-07 03:45:38  No: 106213

nanashiさん、大変参考になりました。ありがとうございます。

>Button1_Click内でlistDialogというform2オブジェクトを宣言していますね。
>で、listDialogというオブジェクトをShowDialogしています。
>つまり入門者さんがform2だと思っているオブジェクトは
>実際にはlistDialogというオブジェクトなんです。
>で、このオブジェクトはButton1_Click内で宣言されているため、
>このイベント内からしか扱えないという事です。
>(分かり難いかもしれませんが、そういうことです。)

ええと、つまりButton1_Clickに対してしかform2は存在しない。みたいな感じでしょうか?
なんとなくならば理解はできました。
それでnanashiさんが修正されたコードを実行してみましたが以下の箇所でエラーがでました。
====================================
(form1)
'form1がアクティブなったときの処理
Private Sub KSmst03_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Activated
    Dim Code As Integer
    Code = listDialog.TCode  ←#この部分です
    TextBox1.Text = Code
End Sub
====================================
エラー内容は
「'System.NullReferenceException' のハンドルされていない例外が 作業実績管理システム.exe で発生しました。

追加情報 : オブジェクト参照がオブジェクト インスタンスに設定されていません。」
といったものでした。
このエラー内容がどんなものか簡潔にはわかりませんが、実行してみて自分でおかしな部分に気づきました。

まず、form1がアクティブになったときのイベントにからませてform2のテキストから値をとってきているわけですが、もちろんform2はform1のボタンを押下しないと開かないわけで、当然テキストに入力もできないわけで・・・
それでいてデバックすると一番最初にはform1は開かれるわけで、開かれた瞬間はアクティブになっているのは当然で・・・(泣)

こういう場合はどういったイベントに処理をからませていけばいいんでしょうか?
自分の理解ではonLoad時にはActivatedは働かないと思っていましたが、そうではないんですね;;

もう少しだけヒントをいただけないでしょうか?


nanashi  2003-03-07 04:47:29  No: 106214

あーなるほどね、ちょっと誤解してました。
form1のLoadイベント内でインスタンスを作成して下さい。
(必ずClosingイベント内でオブジェクトを解放して下さい。)
で、Button1_Click内の
    listDialog = New form2()
を削除、もしくはコメントアウトするのも忘れずに。

あと、もし他の複数のフォームから参照する可能性があるなら
標準モジュール内でPublic宣言しておいたほうが良いです。

> ええと、つまりButton1_Clickに対してしかform2は存在しない。みたいな感じでしょうか?
はい、その通りです。
分かってもらえて嬉しいです(*^-^*)


入門者さん  2003-03-07 21:09:06  No: 106215

何度もすいません。
nanashiさんのご指摘どおりにLoadイベント内にインスタンスを移し変えましたが、同じエラーが出てしまいます(泣)
=====================================================================
    Public listDialog As Form2

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim Code As Integer
        Code = listDialog.TCode  'ここでエラー
        TextBox1.Text = Code
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        listDialog = New Form2()
        'listDialog.ShowDialog()
        Me.DialogResult = DialogResult.OK
    End Sub
=====================================================================
またオブジェクトの開放というのは「object.Clear()」「object.Dispose()」「object = Nothing」というものでいいのでしょうか?
この場合は「listDialog」を開放するのですか?
そう思って以下のようにしたのですが・・・
=====================================================================
    Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
        'listDialog.Clear()    この部分にエラーが出たのでコメントアウトしています。
        listDialog.Dispose()
        listDialog = Nothing
    End Sub
=====================================================================
ものわかり悪くて申し訳ないです(;−;)


nanashi  2003-03-07 23:21:19  No: 106216

> nanashiさんのご指摘どおりにLoadイベント内にインスタンスを移し変えましたが、同じエラーが出てしまいます(泣)

何をしたんでしょうか?
私には何もしてないように見えますが??

インスタンスを作成するというのは
    listDialog = New form2()
という事です。
これをLoadイベント内に入れてください。
もちろん前回言ったとおりButton1_Clickイベントからは削除します。
それとShowDialog()メソッドはコメントアウトしないで下さい。

> またオブジェクトの開放というのは「object.Clear()」「object.Dispose()」「object = Nothing」というものでいいのでしょうか?
> この場合は「listDialog」を開放するのですか?

ここではform2の話をしているのでもちろん「listDialog」です。
    listDialog = Nothing
とします。


入門者さん  2003-03-07 23:55:14  No: 106217

>何をしたんでしょうか?
>私には何もしてないように見えますが??
>
>インスタンスを作成するというのは
>    listDialog = New form2()
>という事です。

すいません、完全に意味がわかっていませんでした(;;
しっかし直してなんとか無事に思い通りの動作ができました^^
これだけのことに随分と時間をかけてしまい非常に申し訳なかったです。
最後まで見放さずにご指導してくださったnanashiさんに心から感謝します^^
以下、参考までに最終のコードを記載しておきます。
=====================================================================
(form1)
Public Class Form1
    Inherits System.Windows.Forms.Form
    
    [WindowsFormDesginerCode]

    Public listDialog As Form2

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        listDialog = New Form2()
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        listDialog = New Form2()
        listDialog.ShowDialog()
        Me.DialogResult = DialogResult.OK
    End Sub

    Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
        'listDialog.Clear()
        listDialog.Dispose()
        listDialog = Nothing
    End Sub

    Private Sub Form1_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Activated
        Dim Code As Integer
        Code = listDialog.TCode
        TextBox1.Text = Code
    End Sub
End Class
---------------------------------------------------------------------
(form2)
Public Class Form2
    Inherits System.Windows.Forms.Form

    [WindowsFormDesignerCode]

    Public TCode As Integer

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        TCode = TextBox1.Text  'TextBox1に入力された値をTCodeに格納
        Me.DialogResult = DialogResult.OK  'form2を閉じる。
    End Sub
End Class
=====================================================================


nanashi  2003-03-08 01:07:42  No: 106218

解決ってことで、やっと私もほっと出来ます(^^;

でもまだ一言。
Button1_Clickイベント内でlistDialogのインスタンスを再作成しないで下さい。
    listDialog = New Form2  '←これをButton1_Click内から削除してください。
こんなことやったことないのでどうなるか分かりません。
仮にうまく動いていてもソース的におかしいので消すべきです。


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

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






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