フォームモジュールで宣言したパブリック変数の扱いで質問があります。
下記のようなテストプログラムを作って実行してみました。
Form1のCommand1ボタンをクリックするとForm2をモーダルダイアログで表示し
Form2のCommand1ボタンでForm2のテキストボックスの値をForm2のパブリック変数
に格納して自信をUnloadします。
'Form1のボタン
Private Sub Command1_Click()
Form2.Show vbModal
Debug.Print Form2.Test 'この段階ではForm2_Loadイベントが実行されず23が返される
Debug.Print Form2.Text1.Text 'この段階ではForm2_Loadイベントがされ23が返される
End Sub
'Form2のGeneral
Option Explicit
Public Test As Long
'Form2のLoadイベント処理
Private Sub Form_Load()
Debug.Print "LOAD"
Text1.Text = Format(Test)
End Sub
'Form2のボタンクリック処理
Private Sub Command1_Click()
Test = CLng(Text1.Text)
Unload Me
End Sub
これを実行するとイミディエートウィンドウに下記のようにメッセージが表示されます。
LOAD ← Form2.Show vbModal の処理でForm2_Loadイベント処理が実行された
23 ←Form1のDebug.Print Form2.Test の処理で23が表示された(Form2のテキストボックスに23と入力したため)
LOAD ←Debug.Print Form2.Text1.Text の処理でForm2_Loadイベント処理が実行された
23 ←←Debug.Print Form2.Text1.Text の処理でForm2.Text1.Textの内容が表示された
そこで質問なんですが、Form2に宣言したパブリック変数の扱いはどうなっているのでしょうか?
Form2のオブジェクトの1つであればDebug.Print Form2.Testと実行するとForm2が再びロードされるような気がしますが
実際はロードされません。しかし、Form2をUnloadした後でも参照可能です。
もしかして、Form2はUnloadされていないのでしょうか?
それともフォームモジュールで宣言したパブリック変数はフォームオブジェクトと別のメモリ管理がされるのでしょうか?
その場合、フォームモジュールで宣言したパブリック変数をメモリ上から解放するということができないのでしょうか?
Unloadした後も一応値が参照できるので、その値を使っていますが、なぜ使用可能なのか分からないので不安です。
長文になりましたが、よろしくお願いします。
すみません、環境を書いていませんでした。
WinXPとVB6です。
確かにちょっと疑問点がありますね。
パブリック変数はそのプロジェクト内からなら
どこからでも参照できるので使えるのは当然かと思います。
Debug.Print Form2.Text1.Textでは
Form2がロードされるのはわかるのですが、
なぜ23が返ってくるのかな?
とりあえずアンロードした後に
Form2.Text1.Textは止めたほうが良いです。
Form2がロードされっぱなしなので。
魔界の仮面弁士さん Sayさん nanashiさん達バトンタッチ!
(勝手に振ってる情けない自分)
okuさん。回答ありがとうございます。
>パブリック変数はそのプロジェクト内からなら
>どこからでも参照できるので使えるのは当然かと思います。
フォームモジュール内で宣言したパブリック変数はフォーム外から使うときは
プロパティの様(Form2.Testみたい)に呼び出さないといけないのでフォーム
オブジェクトの一部なのかなと思っていましたが、標準モジュールに宣言した
パブリック変数と同じ扱いになるということでしょうか?
>Debug.Print Form2.Text1.Textでは
>Form2がロードされるのはわかるのですが、
>なぜ23が返ってくるのかな?
これはおそらくForm2_Loadイベント時に
Private Sub Form_Load()
Debug.Print "LOAD"
Text1.Text = Format(Test)
End Sub
としているのでForm2.Testの値がForm2.Text1.Textに代入されているからだと思います。
なぜForm2.Testの値が継続されて保持されているのかということは上記解釈で
よければ解決するんですが。
あっ確かにForm2のロードイベントでTest変数をText1に入れてますね。
見落としてた!アンロードされてるのになぜ!って思っちゃいました。
フォームもクラス(MSDNに明記されてないですが)なのでオブジェクトを
書かないといけないと思います。
.net等では確かフォームもクラスだと明記されてるので
わかりやすいのですが、VB6では簡単に使えるようにクラスと言うことを
隠して使わせてます。
.net等で標準モジュールがあるか知らないのですが、
>標準モジュールに宣言したパブリック変数と同じ扱いになるということでしょうか?
多分標準モジュールは特異な位置付けになるのかなと思います。
もしかして.netではクラスを推奨してるので標準モジュールなかったりして。
やっぱり私では力不足!
》 あざみさん
> Form2に宣言したパブリック変数の扱いはどうなっているのでしょうか?
このあたりの事情は、MSDNライブラリの検索で、『Visual Basic フォームの有効期間』
という項を調べてみてください。そこに、詳しい解説があります。
もし、それらを見ても分からないようであれば、MSDN内の記述の中で、
どの部分が理解できなかったかを伝えていただければ、解説しますよ。
》 okuさん
> .net等で標準モジュールがあるか知らないのですが、
VB.NETにも、標準モジュールはありますよ。
MSDNのご指摘の箇所を読んでみたところ
「作成されているがロードされていない状態に戻る」
のところにフォームがアンロードされた後でも
「オブジェクトはまだ資源とメモリを保持しています。
フォームのコード部分のモジュール レベル変数に入っている
すべてのデータは、まだ存在しています。
ただし、イベント プロシージャの静的変数はもう存在しません。」
という一文がありました。
これを自分なりに解釈した結果、フォームモジュールで宣言した
パブリック変数がフォームをUnloadしても保持されているのは
「フォームのコード部分のモジュール レベル変数に入っている
すべてのデータは、まだ存在しています」という仕様だと考えました。
そこで、テストプログラムを下記の様に変更し、上記仕様を確認
しました。
'Form1のコマンドボタン
Private Sub Command1_Click()
Form2.Show vbModal
Debug.Print Form2.Test
Set Form2 = Nothing
Set Form2 = New Form2
Debug.Print Form2.Test
End Sub
'Form2のInitializeイベント
Private Sub Form_Initialize()
Debug.Print "Initalize"
End Sub
'Form2のLoadイベント
Private Sub Form_Load()
Debug.Print "Load"
Text1.Text = Format(Test)
End Sub
'Form2のUnloadイベント
Private Sub Form_Unload(Cancel As Integer)
Debug.Print "Unload"
End Sub
'Form2のTerminateイベント
Private Sub Form_Terminate()
Debug.Print "Terminate"
End Sub
これを実行するとイミディエートイベントではの様に表示され
Initalize
Load
Unload
23
Terminate
Initalize
0
Terminate ←これはプログラムを終了した時に表示された。
フォームがUnloadされてもTerminateされていないため
「フォームのコード部分のモジュール レベル変数に入っている
すべてのデータは、まだ存在しています」
の状態が確認できました。
また、Form2を完全に消去後は変数が初期化されていることも
確認できました。
これで安心してフォームモジュールで宣言したパブリック変数の
参照ができます。また、VBの仕組みについても1つ踏み込んで
理解する事ができました。
回答をいただいた皆さん、ありがとうございました。
すみません。解決を押し忘れました。
ツイート | ![]() |