Form間にてテキストボックスの値を操作する方法

解決


JOHN  2003-07-29 18:57:46  No: 107902

サブのForm2上よりメインのForm1上のテキストボックスの値を操作したいのですが、うまくいきません。
Form2(text2が存在)上にて
① Text2 = Form1.text1.Text '値の取得
② Form1.text1.Text = Text2 '値の代入
①、②ともに新たな変数領域が出来てしまったような動きをしています。


nanashi  2003-07-29 20:06:33  No: 107903

※環境は明記して下さい。
  とりあえずVB.NETだと判断し、レスをつけます。

VB6では暗黙のうちにPublicでFormオブジェクト(クラス)が用意されていましたが
VB.NETでは用意されていません。
VB6のように各フォーム間でやり取りをするには、
Form1のスコープ内にForm2が、Form2のスコープ内にForm1が存在しないといけません。

標準モジュールで各フォームをPublicで宣言し、
各フォームの操作はそこで宣言された名前を使ってください。
イベントプロシージャ内でフォームをDim宣言するなんてことは無いように。

初心者はこの辺でつまづいてるみたいですが、VB.NETをやるならクラスについて知っておいた方が良いです。


JOHN  2003-07-29 21:31:03  No: 107904

>※環境は明記して下さい。
すいません。VB6.0です。(でもVB.NETでもやろうと思っていたとこなので参考になりました。)
その後、新たにテスト用プロジェクトを作り試したところ、上記の方法①、②にて問題なくやり取りできました。
しかし、元のプロジェクトでうまくいかず悩んでいます。
以下のように記述しています。
'標準モジュール
Sub Main()
    Set Form1 = New Form1
    Form1.GetInstance
    Load Form1
    Form1.Show
End Sub

'form1
Private Sub Form_Load()
    '---処理---
End Sub
Private Sub Command1_Click()
    Dim Form2   As New Form2
    Form2.Show
End Sub

'form2
Private Sub Form_Load()
    '---処理---
End Sub
Private Sub Text1_Change()
    Form1.Text1 = Text1    ← ①
End Sub

これはテスト用ですが、元のプロジェクトにても同じ流れで記述しています。
違いと言えば、これに加えてユーザーコントロールを数個Form1に貼り付けてぐらいです。

Private Sub UserControl_Initialize()
    Set clsClass = New class1
End Sub
動きとして怪しいと思われるのは、矢印の①にてForm1が既にLoad表示されているにも関わらず、Form1上のユーザーコントロールの上記Initializeが走り、さらに
Form1のForm_Loadも走った後にやっと矢印の①の代入が実行されることです。
矢印の①のForm1.Text1がローカル変数のように見えます。


nanashi  2003-07-29 22:08:33  No: 107905

VB6でこのような記述方法を見たことがないのでちょっとビックリですが……。
幾つか気になった点があります。

> Sub Main()
>     Set Form1 = New Form1
>     Form1.GetInstance
>     Load Form1
>     Form1.Show
> End Sub

VB6では暗黙でフォーム名の付いたオブジェクト(クラス)がPublicで宣言されています。
なので『Set Form1 = New Form1』という記述は普通しません。
それとロード前にフォームのプロパティやメソッド(自作プロシージャ含む)を呼び出すと、自動でロードされます。

> Private Sub Command1_Click()
>     Dim Form2   As New Form2
>     Form2.Show
> End Sub

プロシージャ内でDim宣言した変数やクラスはプロシージャを抜ける時に破棄されます。
VB6では暗黙でフォーム名の付いたオブジェクトがPublicで宣言されていますので
ここでのDim宣言は不要です。
Form2.Showだけで良いでしょう。

> Private Sub Text1_Change()
>     Form1.Text1 = Text1    ← ①
> End Sub

ここはちょっと分かりませんね…。
提示していただいたソースは実際のソースなのでしょうか?


魔界の仮面弁士  2003-07-29 22:44:52  No: 107906

まず、全てのモジュールの先頭に、
Option Explicit
という宣言を入れておいてください。

>    Form1.GetInstance
独自定義のメソッドでしょうか?
(VB6には、GetInstanceというメソッドは存在しませんよね)
 

せて今回の場合、Form1はVBによって暗黙宣言されるフォーム変数ですが、
Form2は、(Form1の)Command1_Clickを押すたびに新規生成されるように
なっていますよね。

となると、問題となっているのは、Newで生成したインスタンスと、
VBが暗黙に生成するフォーム変数とが混同されているのだと思います。

プロジェクト内で、「New Form1」を使っているか、もしくは、
Forms.Add("Form1")を使って、Form1の新規インスタンスを
生成してしまってはいないか、確認してみてください。
また、その逆に、暗黙のForm2変数を使ってしまっている部分が
無いかどうかも確認しておいてください。

なお、『暗黙に作成されるフォームを使用できなくする方法』や
『暗黙に作成されるフォームしか使用できなくする方法』が、
下記のサイトで公開されていますので、参考にしてみては如何でしょうか。
http://www.gj.il24.net/~nakasima/vb/tips/index.htm#VBTIPS16


JOHN  2003-07-29 23:45:28  No: 107907

nanashiさん、魔界の仮面弁士さんどうもありがとうございました。

おっしゃる通り、以下のコードでは何度もForm_Loadが呼び出されていました。
> Sub Main()
>     Set Form1 = New Form1
>     Form1.GetInstance    '独自定義のメソッド
>     Load Form1
>     Form1.Show
> End Sub

Formのメモリ上の状態についてきちんと把握していなかったためでした。

>     Set Form1 = New Form1
自分の考えでは、以下のように理解したのですがどうでしょうか。
暗黙ででフォーム名の付いたオブジェクト(クラス)Aが存在しているにも関わらず、上記の「Set = New」にてフォームのインスタンスBを生成し、これに対してShowをした。
しかし、Form2ではShowされていない暗黙のオブジェクト(クラス)Aに対して以下の処理を行ったため、
>     Form1.Text1 = Text1    ← ①
まだ、暗黙の宣言しかされていないオブジェクト(クラス)Aが、まさに自動でロードされ、フォームのインスタンスAが生成され、それに対して代入処理がなされた。しかし、インスタンスAはShowされているわけではないため、単なる変数に見える。

ということで、シンプルに
'標準モジュール
Sub Main()
    Form1.Show
End Sub

'form1
Private Sub Form_Load()
    '---処理---
End Sub
Private Sub Command1_Click()
    Form2.Show
End Sub

'form2
Private Sub Form_Load()
    '---処理---
End Sub
Private Sub Text1_Change()
    Form1.Text1 = Text1
End Sub

と変更しました。


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

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






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