質問内容が異なるため、たてつづけの質問ですが申し訳ありません。
環境は同じくWinXP、VB.NET2003です。
Form1からForm2、さらにForm3へと移動するとき
Dim frm as New Form3
frm.Show
Me.Close
と記述するこがあると思いますが現在のフォームが消えてから
次のフォームが表示されるまでに間が空く場合があるんですが
上記の例だとForm1(メニュー)からForm2(データ一覧)に移動するのは
一瞬なんですがそこからForm3(データ登録)に移動する時に1〜2秒
間が空いてしまいます。たくさんのコントロールが貼ってあったり
ロードイベントの処理などの理由で画面が重いのかもしれませんが・・・
なにか解決策や、フォーム間の移動をスムーズに行うための
アドバイスなど頂ければ幸いです。よろしくお願い致します。
Form3をHiddenにしとくとかじゃダメですか
レスありがとうございます。
勉強のためのものですが今現在は・・・
Form1:マスタメンテナンスメニュー(スタートアップフォーム)
・〜マスタButtonでForm2へ
Dim frm as New Form2
:
frm.Owner = Me
frm.Show
Me.Hide
Form2:マスタデータ一覧
・データの追加or修正ButtonでForm3へ
Dim frm as New Form3
:
frm.Owner = Me.Owner
frm.Show
Me.Close
・メニューへButtonでForm1へ
Me.Owner.Show
Me.Close
Form3:マスタデータ登録
・前画面へButtonでForm2へ
Dim frm as New Form2
:
frm.Owner = Me.Owner
frm.Show
Me.Close
・メニューへButtonでForm1へ
Me.Owner.Show
Me.Close
以上のような感じでフォーム移動しています。メニューによっては
あと1、2階層下へフォーム移動する所もありますが同様の処理です。
スタートアップフォームはCloseするとアプリ終了になるのでMe.Hideして
いますが、それ以外は基本的にShow→Closeでの移動にしています。
>Form3をHiddenにしとくとかじゃダメですか
との事ですが、仰る意味を正しく読んでいるかが今ひとつ不安ですが
これは例えばForm2を表示する時にForm3もインスタンスしておいて
Showはせず必要な時がきたらShowする・・・といった事でしょうか?
ただ、全くの初心者の勘ですが今度はForm2を表示する時に間が空くとか・・・
.NET環境のPCで勉強できる時間が限られているので質問が予測や説明で長くなってすいません。
>ただ、全くの初心者の勘ですが今度はForm2を表示する時に間が空くとか・・・
Form2 を表示してから Form3 のインスタンスを生成すればいいのでは?
『必要な処理時間は、カーソルを砂時計にして待つ』のも王道な気はします。
実力とも相談してください。
扱いは難しい内容を含みますが、『マルチスレッド』をヘルプ(MSDN)で調べて
みてください。
>スタートアップフォームはCloseするとアプリ終了になるので
仕様?それともそれ以外の方法を知らないだけ?方法は色々とありますが、結局、
重いフォームを何度も生成・破棄するなら、プログラム全体の負荷が上がりますので、
初回に生成した後は非表示します。この手法を使う場合は、プログラム終了時に
非表示のフォームが残ったりしないように気をつける必要があります。
たとえば↓
http://madia.world.coocan.jp/cgi-bin/VBBBS/wwwlng.cgi?print+200602/06020024.txt
特攻隊長まるるうさん、親切かつ丁寧な回答感謝します。
今回質問させて頂いた裏にはこういった場合回答者の方々ならどうしているんだろ?という思いもあったので
>『必要な処理時間は、カーソルを砂時計にして待つ』のも王道な気はします。
のように「こうゆう手もある」みたいな書込みは大変勉強になります。
もちろん今の私の実力の範疇ではないのでしょうが、いずれは・・・という気にはなります。
>初回に生成した後は非表示します。
が今のところ最善策な気はしますが、例えばForm1〜Form5の間を行き来したとして
真ん中のForm3が重いフォームとして初回生成後から非表示にした場合隠れている間は
どのように監視(管理)するかなどすぐにはイメージできそうもないですが。
いずれにせよ助言頂いたヘルプやリンクなど何度か読み直す覚悟で参照してみたいと思います。
>仕様?それともそれ以外の方法を知らないだけ?
ですが、"知らないだけ"の方だと思います。一部のフォームには終了Button
があるのでその場合はApplication.Exitでその場で終了していますが
それ以外は基本的にメニューに戻って終了Button押下という感じなので
Ownerをずっと受渡ししてどのフォームからもMe.Owner.Showで一気に
メニューへ戻れるようにしています。
・・・そういう意味では↑の初回生成後は非表示の件も似たような事が言えるのかな・・・?
画面展開は基本的な部分だと思うので色々なパターンを覚えられたらと思います。
>>『必要な処理時間は、カーソルを砂時計にして待つ』のも王道な気はします。
>のように「こうゆう手もある」みたいな書込みは大変勉強になります。
>もちろん今の私の実力の範疇ではないのでしょうが、いずれは・・・という気にはなります。
いや、逆(^^;)。待ち時間を改善しないで、カーソルを変更するだけなので、
いちばん簡単な方法です。
[VB.NET2003]
Me.Cursor = Cursors.WaitCursor
> Dim frm as New Form2
> :
> frm.Owner = Me
> frm.Show
Me.Cursor = Cursors.Default
> Me.Hide
>初回生成後から非表示にした場合隠れている間は
>どのように監視(管理)するかなどすぐにはイメージできそうもないですが。
とりあえず『隠れている』は置いておいて、
[VBレスキュー,花ちゃん .NET Tips フォーム]
http://www.bcap.co.jp/hanafusa/dotnet/form02.htm
>3.Form1 から Form2 をモードレスで複数表示されないように表示する
の f2 のように、ローカル変数を使わず、グローバルな変数に参照アドレスを
格納しておけば、以降、その変数に命令する形で実行できます。
ただし、今回の質問の場合、Form2 → Form3 や Form3 → Form2
があるので、どこでフォームの参照アドレスを入れた変数を管理するかが
問題となります。いちばん簡単な方法は、全てのフォームが利用できる
Module や親クラスなどを用意し、そこに渡しておくことでしょう。
ちょっと理解するのが大変かもしれませんが、Sub Main 起動にして
実行してみて下さい。
[VB.NET2003]
'/// Class1.vb
Public Class Class1
Inherits ApplicationContext
Public Shared Sub Main()
Application.Run(New Class1)
End Sub
Private Sub Form_ExitThread()
Dim i As Integer
Me.mClosingCancel = False
'全てのフォームを閉じる
With Me.mForms
For i = 0 To .Count - 1
DirectCast(.Item(i), Form).Close()
.Item(i) = Nothing
Next
End With
'スレッド終了
MyBase.ExitThread()
End Sub
Private Sub Form_FormChange(ByRef sender As Form, ByVal TargetFormNum As Class1.FormsNum)
sender.Hide() 'イベントを起こしたフォームを非表示にする
DirectCast(Me.mForms(TargetFormNum), Form).Show() '移動後のフォームを表示
End Sub
Private Sub Form_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs)
If mClosingCancel Then
e.Cancel = True 'フォームが閉じるのをキャンセル
MessageBox.Show("『終了』ボタンで終了してください。")
End If
End Sub
Public Enum FormsNum
Form1
Form2
Form3
End Enum
Private mForms As ArrayList
Private mClosingCancel As Boolean
Private Sub New()
Dim F1 As New Form1 'プログラム起動時に全てのインスタンス生成
Dim F2 As New Form2
Dim F3 As New Form3
'プログラム終了イベント
AddHandler F1.ExitThread, AddressOf Form_ExitThread
AddHandler F2.ExitThread, AddressOf Form_ExitThread
AddHandler F3.ExitThread, AddressOf Form_ExitThread
'表示フォーム変更イベント
AddHandler F1.FormChange, AddressOf Form_FormChange
AddHandler F2.FormChange, AddressOf Form_FormChange
AddHandler F3.FormChange, AddressOf Form_FormChange
'Closing イベント
AddHandler F1.Closing, AddressOf Form_Closing
AddHandler F2.Closing, AddressOf Form_Closing
AddHandler F3.Closing, AddressOf Form_Closing
Me.mForms = New ArrayList(New Form() {F1, F2, F3})
Me.mClosingCancel = True
F1.Show()
End Sub
End Class
'/// Form1.vb
Public Event FormChange(ByRef sender As Form, ByVal TargetFormNum As Class1.FormsNum)
Public Event ExitThread()
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'Form2へ
RaiseEvent FormChange(Me, Class1.FormsNum.Form2)
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
'Form3へ
RaiseEvent FormChange(Me, Class1.FormsNum.Form3)
End Sub
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
'終了
RaiseEvent ExitThread()
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.Button1.Text = "Form2へ"
Me.Button2.Text = "Form3へ"
Me.Button3.Text = "終了"
End Sub
'/// Form2.vb
'/// Form3.vb
Form1.vb をコピペし、適当にイベントの引数などを変更してください。
うおーースゴイっす!めちゃくちゃテキパキ動きますよぉ!
特攻隊長まるるうさん本当に有難うございます!m(_ _)m
本来ならば最初に貼って頂いた過去ログで何とかしないといけない所を今回の質問に沿った
サンプルまで提示して頂いて、頭が上がりません。かなり感激しております。
Sub Mainでの起動は参考書でスプラッシュフォームを表示するサンプルをコーディングしたことは
ありますがそれにしてもApplication.RunメソッドでSub Mainを記述している
スタートアップClassをNewするなどは思いもつきませんでした。ちなみにこの
起動時に全てのインスタンスを生成するという方法は、一般的にはどの程度の
数までなら有りなんでしょうか?フォームが十数個もある場合はやはりNGでしょうか?
また今回の回答内容を理解していこうとする上で他にもかなり勉強できました。
ByRefとByValの違い(変数の値を変更できる・できない)
EventとRaiseEvent(ユーザー定義のイベントの宣言・発生)
Enum(列挙体を宣言)
DirectCastはCtypeでもいいそうですね。
AddHandler(イベントハンドラの関連付け)は今まではHandles句の後に
同イベントを記述していくくらいしか知りませんでした。
ついこの間まで参考書片手にサンプルをコーディングするしか能がなかったので
少しは開発チックなコードが打てるようになった気がして面白くなってきました。
質問内容とは関係ありませんが、合わせてお礼させてくださいm(_ _)m
本日、今回のやりとりによって得た内容をド新人仲間たちにも教えました。
個人差(理解に)はあるでしょうが皆それなりに感心してくれています。
目標は十分に達成できましたので解決とさせて頂きます。ありがとうございました。
あとはやはりフォームの数が多い場合などが気になりますが色々試せればと思います。
それと質問自体は解決なんで、できればでいいんですが教えて下さい。
コード中のイベントを操作している部分にかなり興味を持ちまして・・・
これはクラスにあらかじめ用意されいるイベントとは別に、自分で何らかの
目的を持ったPublicなイベントを宣言(Event)し、かつイベント検出ポイント
を設定(RaiseEvent)してやることで、そのクラス(今回はForm1)を使用する
側では、通常私たちがButtonクラスのClickイベントハンドラに処理を記述
するのと同じようなことができようになる
といった考え方(使い方)であっているでしょうか?
正確には完全にド新人さんの要求を満たしたコードではないと思います。
# 初心者・通りすがりなどの匿名や捨てハンは嫌われますが、
# 理由の一つとして、こちらから呼びかける時に、ものすごく
# 違和感を感じるというのがあると思います。匿名や捨てハンは
# 相手に『自分に関わるな』と言っているのと同じです。質問
# しておいてそれは無いでしょう?たとえ、実力がまだまだだと
# 思ったとしても、回答者と対等の立場で調べ(回答者が全く
# 調べないで回答することは稀です)、解決していこうという
# 意思があるなら、自分の個性を出し、長く使える固定ハンドルを
# 考えましょう。尤も、本当に捨てハンなら仕方ないですが。。。
フォームを入替えるたびに New していたというのが、フォームを
頻繁に入替えるプログラムでは、問題になります(通常、ちょっとした
ダイアログや軽いフォームは使用時に New し、使わなくなったら
破棄します。つまり質問時のコードを一般的に使っています。)が、
そこは非表示にして解決できたと思います。
ただし、フォームを1回通り New する時間は必要なままで、
フォームが多くなればプログラム起動がどんどん遅くなります。
>起動時に全てのインスタンスを生成するという方法は、一般的には
>どの程度の数までなら有りなんでしょうか?
数は関係ないでしょう?今回の質問も、1つのフォーム自体が軽
ければ、毎回 New したのでも良かったのでは?実際にフォームを
十数個使った場合に、プログラム起動までに何秒掛かって、それを
許すかどうか?は使う人次第です。
例えば、Excel なんかも初回起動時などはかなり時間が掛かったり
しませんか?ある程度は我慢してくれると思います。
プログラマとして許すかどうかは自分で使ってみて判断してください。
ボクの場合は、プログラム起動を選んでから3秒、何か画面に表示
されてから砂時計表示で更に5秒…を超えないように努力しています。
# [VB.NET]で大きなプロジェクトの起動なんて30秒以上掛かります
# けど『仕方ない』と諦めてくれる場合もありますよね(^^;)
そこをどうにかする方法もあります。例えば、プログラム起動時は
空の配列(Class1 の mForms)だけ用意し、初めてフォームが
必要となった時(Form_FormChange イベント内)で、まだ New
されていなければ New を実行、次回からは配列内の実体を
利用するという形に、ボクのコードを改造できると思います。
相変わらずトータルの待ち時間が少なくなる訳ではありませんが、
分散されてストレスが軽減されます。
その場合は、既にリンクを貼ってありますが、VBレスキュー,
花ちゃんさんのサンプルコード
> If f2 Is Nothing OrElse f2.IsDisposed Then
の判定式を利用してみてください。
また、トータルの待ち時間を少なくする方法もあります。
実際にトータルの処理時間が少なくなっているわけでなく、
同時に複数の処理を実行するのですが…。
それが、これもまた、既にキーワードだけは示しております
『マルチスレッド』です。
感覚としてはもう1つプログラムを走らせて、2つの処理を
同時に行うと言ったらよいでしょうか?つまり、メニューの
フォームを表示するプログラムの裏で、他のフォームを
New するプログラムを走らせるわけです。極端な話、
フォームの数だけスレッドを用意し、それぞれに1つずつ
フォームを New させれば、理論上は最短の処理時間に
なるのかもしれません。
ただ、マルチスレッドは扱いが難しい部分があるのです。
興味があるなら、まずはヘルプをはじめ、情報収集から
はじめてください。自分でサンプルプログラムを2・3個
作って、どんな使い方にどんな問題点があるか?…が
分かってからでないと、使用すること自体をお勧めできません。
>それにしてもApplication.RunメソッドでSub Mainを記述している
>スタートアップClassをNewするなどは思いもつきませんでした。
そこは最初に回答した時のリンク先で、魔界の仮面弁士さんが
書いてるコードの流用なので、ボクも思いつきませんでしたw。
>DirectCastはCtypeでもいいそうですね。
CType の方が処理時間は遅いです(微々たるものですが)。
CType の方が汎用性があります。
詳細はヘルプで確認下さい。
[DirectCast]
http://msdn2.microsoft.com/ja-jp/library/7k6y2h6x.aspx
型変換(キャスト)には他にも特定の型専用のものも用意されています。
『型変換』などをキーワードに調べてみてください。
>これはクラスにあらかじめ用意されいるイベントとは別に、自分で〜
イベントついて分からないのであればヘルプで『イベントの利用』などの
キーワード検索をしてみてください。
[イベントの利用]
http://msdn2.microsoft.com/ja-jp/library/2ccyd347.aspx
今気づいたんだけど、ヘルプ(MSDN)のグループ(画面左のツリー)で
[開発の基本]とかいう分類になってるね(^^;)基本らしいですよwどうします?(爆
ハンドルについてのご指摘についてですが
質問者としてのド新人は私一人です。が、社内では新人チーム4名(ド新人仲間たち)で行動しています。
ちなみに自由に使えるPCは2台だけなので
>.NET環境のPCで勉強できる時間が限られているので
だったりしています。で、その2台を使えない時や帰宅後などに別のPCや
自宅のPCなどで私が代表して質問をして結果を他3名に教えておりました。
ですが、これからもお世話になることは間違いないので
特攻隊長まるるうさんの仰る通りちゃんとした固定ハンドルを考えます。
その方が多少ずつでも成長していく所をお見せできるかもしれませんしね。
それとも、仮に初心者の域を脱する事ができたとしても「ド新人」でいくかですね(^^)
とても親切な回答を度々付けて頂き誠に恐れ入ります。
確かにサンプルを提示してもらい動作検証した時点で満足しておりました。
>必要となった時(Form_FormChange イベント内)で、まだ New
>されていなければ New を実行、次回からは配列内の実体を
>利用するという形に、ボクのコードを改造できると思います。
あたりは早速修正して動作テストできそうです。しかも
>> If f2 Is Nothing OrElse f2.IsDisposed Then
>の判定式を利用してみてください。
など、おそらくつまずくであろう事柄についてあらかじめアドバイスまで
して頂いて本当に有難うございます。
マルチスレッドなどにしても何度か読んで試した経験があれば後々になって
生きてくると思うので手分けして情報収集していきたいと思います。
>基本らしいですよwどうします?(爆
どう答えればいいんでしょう?
開発デビュー前の自分等にとっては今が基本を知る時だと思ってるので頑張ります!
>確かにサンプルを提示してもらい動作検証した時点で満足しておりました。
そうね(^^)。あくまで掲示板に書込むのはサンプル…ほとんどその場で
考えてるから、改良の余地なんて無数にあります。自分の目的に合わせて
カスタマイズできなきゃ価値は半減します。
…そんな言葉は久しぶりに聞いたよ。
# 初心者なんて名前の付いてる掲示板だからか?動作検証なしで
# コピペして、そのまま使う人も多いから。。。著作権なんて頭に無いし。。。
>どう答えればいいんでしょう?
いや、そこ、普通に苦笑いしてもらうところ。。。(^^;)
上に書いたような調子なので、紹介したイベントに関しての内容を基本だと
思えて、頑張れるのならすごいと思います。ヘルプの言葉使いって独特で、
初心者だと1割理解できれば優秀だからね。しかもヘルプの[開発の基本]に
書いてあることを理解できれば、かなりのレベルになってる気が…(汗)
ところがマイクロソフトの基準では、開発者レベルで基本的な内容だと…
思っているのかなぁ???って苦笑いして頂ければと思いますm(__)m
まぁ、そんな頑張らんでもいいんで、分からんようなったら、また来んさい。
ツイート | ![]() |