同じフォームから複数の画面を立ち上げ、それぞれの画面での処理を識別するには?

解決


一休  2005-09-02 23:02:46  No: 124757

Dim oForm() As Form1
Dim nCnt as long

nCnt = nCnt + 1
ReDim oForm(nCnt)

Set oForm(nCnt) = New Form1

oForm(nCnt).Show 

複数枚(数は未定)のフォームを立ち上げて、それぞれのフォームで
それぞれ別の処理を行いたいのですが、上記の通りでは最後にアクティブ
だった画面の処理しか行えません。
どのようにすれば、全ての画面で処理出来るようになるでしょうか?又、
それを識別するにはどういった方法がありますでしょうか?
ご教示お願いします。


特攻隊長まるるう  2005-09-03 02:06:56  No: 124758

ReDim ステートメントのヘルプは読みましたか?
Preserve を指定してみて下さい。

それと
>Dim oForm() As Form1
変数の有効範囲(スコープ)は大丈夫ですか?
これもヘルプ…または入門書に書いてある基礎レベル
の知識です。分からないなら調べてきて下さい。


一休  2005-09-03 02:56:05  No: 124759

特攻隊長まるるうさん、有難うございます。
勉強不足ですいません。
Preserveは追加しました。フォームの宣言部ですが、こちらはPublicで宣言して
いるのでスコープは問題ないかと思っていたのですが・・・。

失礼いたしました。
>Dim oForm() As Form1
>Dim nCnt as long

正しくは
Public oForm() As Form1
Public nCnt As Long
です。

画面が、何枚立ち上がっているかカウント
して識別しようと試してみたのですが、最後にカウントした画面
の処理しか出来ませんでした。
何か他に方法があれば教えて頂けますか?


Geo=TK3  2005-09-03 23:24:38  No: 124760

>Public oForm() As Form1
>Public nCnt As Long

とりあえずスコープは問題ないようですね。
後はこの宣言が標準モジュールでされているかどうかが
気になりますが。

>画面が、何枚立ち上がっているかカウント
>して識別しようと試してみたのですが、最後にカウントした画面
>の処理しか出来ませんでした。

oForm(nCnt) に対して何らかの処理を試みているのであれば
当然最後に作成した画面に対してしかその処理は行われませ
んが...

>何か他に方法があれば教えて頂けますか?

oForm 配列の中から実際に処理を行わせるフォームを見つけ
てから、そのフォームで行いたい処理を実行してみてください。

例示のコードでフォームを生成しているなら最初に作成した
フォームなら oForm(1) 、2 番目に作成したフォームなら 
oForm(2) になる筈です。
# ただし nCnt の初期値が 0 だった場合。

この時に、例えば最初に生成したフォームを表示するなら以下の
ようになります。

oForm(1).Show


一休  2005-09-05 19:28:03  No: 124761

Geo=TK3さん、有難うございます。
変数は標準モジュールで宣言してあります。

>oForm 配列の中から実際に処理を行わせるフォームを見つけ
>てから、そのフォームで行いたい処理を実行してみてください。

この方法を考えていたのですが、フォームの枚数をカウントして
いって、実際に複数枚開いたフォームが自分が何枚目に開かれた
フォームであるかという認識をさせればよいかというところで、
つまずいています・・・。
Tagプロパテ等が有効になるのでしょうか?


特攻隊長まるるう  2005-09-05 19:50:40  No: 124762

そろそろ開発環境を書いてくれないと回答できないです。
[VB6.0]だと思って回答してます。

>つまずいています・・・。
質問の意味を把握できません。
Geo=TK3 さんの書き込みには答えまで書いてあるわけですが、
どの部分がどう分からないのか説明して下さい。
>例示のコードでフォームを生成しているなら最初に作成した
>フォームなら oForm(1) 、2 番目に作成したフォームなら 
>oForm(2) になる筈です。
># ただし nCnt の初期値が 0 だった場合。
>この時に、例えば最初に生成したフォームを表示するなら以下の
>ようになります。
>oForm(1).Show


一休  2005-09-05 20:22:54  No: 124763

特攻隊長まるるうさん、書き込み有難うございます。
開発環境はVB6.0です。

複数枚立ち上がっているフォームが何番目に立ち上げたものかというのを、
どうすればフォームに認識させる事が出来るのかという事でつまづいておりました。
言葉足らずですいませんでした。

やりたい事はMDIフォームを使って、メイン画面のツールバーのボタンをクリックする事で、
検索画面を立ち上げます。ここで、クリックした回数分だけ検索画面を複数枚
立ち上げ、それに対応する分だけ検索結果画面をMDIの子フォームとして
表示させたいのです。 
3枚、検索画面が立ち上がっているとしてそれぞれの画面で検索を実行したいのですが、
その際にそれら画面が別のものであるという識別をする方法で悩んでいます。


特攻隊長まるるう  2005-09-05 20:38:39  No: 124764

>変数は標準モジュールで宣言してあります。
という事は全てのフォーム(MDI親フォーム・MDI子フォーム)
を通して同じ変数を使っていると言う事ですよね?。
…であるなら、MDI子フォームを立ち上げる毎に変数 oForm
にフォームの参照アドレスを格納できているのであれば
>複数枚立ち上がっているフォームが何番目に立ち上げたものかというのを
 oForm(0)'一番目に立ち上げたもの
 oForm(1)'二番目に立ち上げたもの
 oForm(2)'三番目に立ち上げたもの
 …
なのでは?フォームが複数あるので
>3枚、検索画面が立ち上がっているとしてそれぞれの画面で検索を実行したいのですが、
>その際にそれら画面が別のものであるという識別をする方法で悩んでいます。
では意図が通じません。
MDI親フォームの名前を MainForm1
MDI子フォームの名前を ChildForm1 ChildForm2 ChildForm3
とした時、どのフォームで何が分かればいいのですか?


通ってみた  2005-09-05 20:38:42  No: 124765

>>複数枚立ち上がっているフォームが何番目に立ち上げたものかというのを、
>>どうすればフォームに認識させる事が出来るのかという事でつまづいておりました。

ざっと見た感じで100番目なら

oForm(100).Show

とかでいいんじゃないの?
少しサンプルをいじってどう動作するか確認してみては?
開きたい番号が変数に入っているなら、その変数を指定するだけではダメなんでしょうかね

3つのフォームで同時に、とかいうのなら、For〜Nextなりで3回ループさせてやればいいのでは?


一休  2005-09-05 21:10:55  No: 124766

特攻隊長まるるうさん、通ってみたさん、書き込み有難うございます。 

MDI親フォーム、Main Form1のツールボタンをクリックして検索画面、ChildForm1(1)、ChildForm1(2)、ChildForm1(3)
として、それぞれで検索した検索結果をChildForm2(1)、ChildForm2(2)、ChildForm2(3)に表示させたいと思っています。
カウントで枚数を数えていくと、ChildForm1(3)は動作しますが、ChildForm1(1)、ChildForm1(2)では動きません。
それは、カウント変数では識別子としての役割は出来ないのかと思って他の方法を模索しておりました。

>開きたい番号が変数に入っているなら、その変数を指定するだけではダメなんでしょうかね

カウント変数にそれぞれ値は入ってはいるのですが、ChildForm1が複数枚ロードされてしまっているので、
それと同時にカウントもされており、最後に立ち上げたフォームでしかカウント変数によっての動作を行えないのかと
思ったからです。


ガッ  2005-09-05 21:39:11  No: 124767

横からごっそり失礼します。

※とりあえず、配列じゃなくてコレクションにしてみてはどうでしょう…

動作の切り分けがあいまいに感じます。
現在は、
・検索するFormと表示するFormが混ざっている。
という状況でしょうか?

この場合、Formに対して次のようなインタフェイスを実装してみてはどうでしょう?
・"検索する"というメソッド(外部から呼ばれる)
・"検索した"というメソッド(イベントが発生した時に呼ばれる)
こうすれば、ChildForm1が検索され且つ、表示されるFormとすることが出来ます。

土台が「カウント」や「添え字」では、操作対象があいまいになりがちです。
はっきりと「検索対象」と「表示対象」を取捨選択できるようにしておきましょう。

-インタフェイス例-
'ISearch.cls
'このインタフェイスを実装するFormは、
'自身を検索対象とすることが出来るようにする
public sub SearchThis()
end sub

'IShowFoundData.cls
'このインタフェイスを実装するFormは、
'自身に検索結果(どこからか引っ張ってくる)を表示できるようにする
public sub ShowFoundData()
end sub

で、これらをChildForm1とかChildForm2などのImplementsしておきます。
その後、
・"検索対象にするForm"をまとめるコレクション:cltSearch
  →ISearchを実装したFormをまとめます
・"表示対象にするForm"をまとめるコレクション:cltShowFoundData
  →IShowFoundDataを実装したFormをまとめます

上記の結果として、次のようなことをシミュレートします
・検索し、結果を表示する
Public Sub Find_and_Show()
    Dim sch     As ISearch
    Dim sw      As IShowFoundData
    
    'cltSearchに検索対象のFormをAddしていきます
    '...
    'その後、cltSearchを処理していきます
    For Each sch In cltSearch
        Call sch.SearchThis
    Next
    
    'その後、cltShowFoundDataを処理していきます
    For Each sw In cltShotFoundData
        Call sw.ShowFoundData
    Next
End Sub

※…と、暴走気味に自分なりの考えを書いてしまいました(TT
  長文失礼しました。
  …英語ダメなのは気にしないで…(orz


特攻隊長まるるう  2005-09-05 22:38:16  No: 124768

配列を使うかコレクションを使うかは今後の話として、
>カウントで枚数を数えていくと、ChildForm1(3)は動作しますが、
>ChildForm1(1)、ChildForm1(2)では動きません。
この動作がおかしいです。現在の動作のほうがおかしいんです。
MainForm1(Main の後にスペース入れないで〜 ParentForm1 の
方が良かった?)で標準モジュールの oForm に子フォームの参照を
入れてますか?入れた時点ではその子フォームを動作させられるん
ですよね?次に呼び出されるまでに oForm が初期化されてませんか?
Preserve じゃ引き継がれないのかなぁ…調査してみます…。


特攻隊長まるるう  2005-09-05 23:17:45  No: 124769

調査終了。こちらでは問題なくいつでも全てのフォームの実体へ命令できます。
えっと。oForm() が初期化されて Form1 の参照が消えてるなら、Form1
側の処理を走らせようとした時にエラーになると思います。エラーは発生して
ますか?発生して無いなら単なる勘違いの可能性もあるかも…。
>ChildForm1(3)は動作しますが、ChildForm1(1)、ChildForm1(2)では動きません。
この判断はどうやってしていますか?


一休  2005-09-05 23:35:53  No: 124770

ガッさん、特攻隊長まるるうさん、有難うございます。

エラーは発生していません。
>この判断はどうやってしていますか?
検索画面ChildForm1で引き継いできたoForm(nCnt)の値が、oForm(3)になっていたからです。
説明不足だったかもしれませんが、連続して検索画面ChildForm1を立ち上げています。
カウント変数では、最後にカウントした値がChildForm1に引き継がれるのは当然ですよね。。。
だから、例えば3枚画面を立ち上げた時にChildForm1(1)、ChildForm1(2)が動かないのかと思っていたのですが。

>標準モジュールの oForm に子フォームの参照を入れてますか?
勉強不足で申し訳ありませんが、参照を入れるとはどういう事でしょうか。


特攻隊長まるるう  2005-09-05 23:55:01  No: 124771

>>標準モジュールの oForm に子フォームの参照を入れてますか?
>勉強不足で申し訳ありませんが、参照を入れるとはどういう事でしょうか。
単純に
   Set oForm(nCnt) = New Form1
の事です。変数には『値型』と『参照型』があります。Form を型とする
変数の場合『参照型』になります。メモリ上の実体(Form のインスタンス)
を参照するアドレスが格納されます。親フォームでちゃんと全ての子フォーム
の参照を変数にセットできてますか?ってのが聞きたかったのです。

なんか関係ない所でハマってる気がするんですが…。
>だから、例えば3枚画面を立ち上げた時にChildForm1(1)、
>ChildForm1(2)が動かないのかと思っていたのですが。
思っているだけじゃなくテストして確認して下さい。
[VB6.0]
'/// MainForm1(MDIForm1.frm)
Option Explicit
Private Sub MDIForm_Load()
    nCnt = -1
    Me.Caption = "MainForm1"
End Sub
Private Sub mnuAdd_Click()
    nCnt = nCnt + 1
    ReDim Preserve oForm(nCnt)
    Set oForm(nCnt) = New Form1
    With oForm(nCnt)
        .Caption = "ChildForm" & CStr(nCnt)
        .Show
    End With
End Sub
Private Sub mnuRun1_Click()
    If nCnt < 0 Then
        MsgBox "Form1 が1つも開かれていません。"
        Exit Sub
    End If
    oForm(0).MsgShow
End Sub
Private Sub mnuRun2_Click()
    If nCnt < 1 Then
        MsgBox "Form1 をもう1つ開いて下さい。"
        Exit Sub
    End If
    oForm(1).MsgShow
End Sub

'/// Form1(Form1.frm)
Option Explicit
Public Sub MsgShow()
    MsgBox Me.Caption
End Sub

'/// Module1(Module1.bas)
Option Explicit
Public oForm() As Form1
Public nCnt As Long


一休  2005-09-16 19:43:44  No: 124772

お蔭様で解決しました。
画面のインスタンスを作成し、それぞれのTagプロパティに
値を代入することで識別子としての役割を果たせました。
どうも有難うございました。


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




  


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