DOBON.NET DOBON.NETプログラミング掲示板過去ログ

Form_Load中に別FormをLoadしていますが・・・

環境/言語:[環境:XP,PPC2003SE 使用言語:VB2005 .NET CompactFramework2.0]
分類:[.NET]

初めまして。
初めて投稿致します。至らない部分があるかも知れませんが宜しくお願い致します。
VB2005から始めたばかりです。
スマートデバイス(PDA)で動作するソフトを作成しています。

現在、下記のようにMainFormを起動させています。
MainFormのLoad内でForm1--->Form2の順で2つのLoadを実施しています。
表示上はForm2が最前面に来ていますが、Focusがないのか(?)、タイトル部分
はMainForm名が表示され、画面をタップした時点で漸くForm2のタイトルが表示
されます。Form2上のTextBoxにもカーソルがありません。
また、右上の×をタップすると、Form2が消え(Visible = False?)、Form1が
最上位画面になります。これはタイトルも画面部分も表示されています。

MainFormのロード直後に、Form1,2をロードすれば良いのですが、そのイベント
が判りません。また、MainFormをロードした時しか、Form1,2を2つロードする
ことはありません。
宜しくお願い致します。

Public Sub Main()
Application.Run(New MainForm)
End Sub

Private Sub MainForm_Load(ByVal sender As Object, _
  ByVal e As System.EventArgs) Handles MyBase.Load

  Dim frm1 As New Form1
  Dim frm2 As New Form2

  frm1.Show()
  frm1.Activate()
frm2.Show()
frm2.Activate()
End Sub

==== Form1 ====
Private Sub Form1_Load(ByVal sender As Object, _
  ByVal e As System.EventArgs) Handles MyBase.Load
Me.Refresh()
Me.Focus()
Me.TopMost = True
End Sub

==== Form2 ====
Private Sub Form2_Load(ByVal sender As Object, _
  ByVal e As System.EventArgs) Handles MyBase.Load
Me.Refresh()
Me.Focus()
Me.TopMost = True
End Sub
> MainFormのLoad内でForm1--->Form2の順で2つのLoadを実施しています。
> 表示上はForm2が最前面に来ていますが、Focusがないのか(?)、タイトル部分
> はMainForm名が表示され、画面をタップした時点で漸くForm2のタイトルが表示
> されます。Form2上のTextBoxにもカーソルがありません。

MainFormのLoadのEndSubが最後のためと思われます。

> MainFormのロード直後に、Form1,2をロードすれば良いのですが、そのイベント
> が判りません。また、MainFormをロードした時しか、Form1,2を2つロードする
> ことはありません。

ActivateイベントでLoad直後かどうかを自前のフラグなどで判断してください。
■No15049に返信(まどかさんの記事)
ご回答有り難うございました。

> ActivateイベントでLoad直後かどうかを自前のフラグなどで判断してください。

早速、下記の通り試してみました。
自前のフラグとはこういう事だと理解しておりますが、結果的には同じ事象になります。
タイトルの動きを見るとちらつきのように見えるのですが、下記の通りです。
MainForm--->Form1--->Form2--->MainForm の順に見えます。

'自前のフラグ
Public bInitFlag As Boolean

==== MainForm ====
Private Sub MainForm_Activated(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Activated
If bInitFlag = True Then
Dim frm1 As New Form1
Dim frm2 As New Form2
frm1.Show()
frm1.Activate()
frm2.Show()
frm2.Activate()
End If
bInitFlag = False
End Sub

Private Sub MainForm_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
bInitFlag = True
End Sub

==== Form1 ====
Private Sub Form1_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Me.Refresh()
Me.Focus()
Me.TopMost = True
End Sub

==== Form2 ====
Private Sub Form2_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Me.Refresh()
Me.Focus()
Me.TopMost = True
End Sub
すいません、よく見ていなかったのですが、
TopMostにするのは何か理由があるのでしょうか?

また、Form1,2のRefreshとFocusは確実に要りません。
まだ描画されてませんので。
Form1.Activateも特に要らないような気がします。

Application.DoEvents()
Form1.Show()
Form2.Show()
とかだめですか?
あ、CompactFramework特有のお話の場合だとわかりません。。。m(_ _)m
> MainFormのロード直後に、Form1,2をロードすれば良いのですが、
本来なら、Application.Run に(Formではなく)ApplicationContext を
渡したたい所なのですが、Compact Framework では非サポートなんですよね…。


> また、MainFormをロードした時しか、Form1,2を2つロードする
> ことはありません。
3 つのフォームを同時に表示させなければいけないのでしょうか?

Pocket PC 系の OS の場合、各フォーム(ダイアログを除く)は、
http://msdn.microsoft.com/library/ja/jpdnnetcomp/html/NetCompactFrameWorkFAQ.asp
の 4.8 にもあるように、一つのフォームが、画面いっぱいに表示されるのが
基本だと思いますので、複数表示させるなら、親子関係を持ったモーダル
あるいはモードレスのダイアログにする事になると思いますが、各フォームの
BorderStyle は、どのように設定されているのでしょうか?
■No15052に返信(まどかさんの記事)
何度も回答頂き、ありがとうございます。
> すいません、よく見ていなかったのですが、
> TopMostにするのは何か理由があるのでしょうか?
TopMost = True にしたことで初めて最前面に画面が表示させたい為です。
 
> また、Form1,2のRefreshとFocusは確実に要りません。
> まだ描画されてませんので。
> Form1.Activateも特に要らないような気がします。
はい、判りました。
削除して確認したところ、影響なく表示されました。
ありがとうございます。

> Application.DoEvents()
> Form1.Show()
> Form2.Show()
> とかだめですか?
上記の通り、MainFormのActivateイベント内に

Private Sub MainForm_Activated(ByVal sender As Object, _
    ByVal e As System.EventArgs) Handles MyBase.Activated
    If InitFlag Then
        Application.DoEvents()
        frm1.Show()
        frm2.Show()
    End If
End Sub

としてみましたが、MainFormの裏側に画面が居るようです。
MainFormの終了と同時に、一瞬2つの画面が見えます。

MainFormが完全に表示しきった時間を待ってみて、仮にMainForm上にボタンを
貼り付け、frm1とfrm2を同時に呼び出してみました。
すると期待する通りの動きになるので、Activateイベントの終了時点で、
MainFormにFocusが移っているようです。
Activateイベント内でTimerを起動して、時間を稼ぐ方法で考えてみます。
■No15054に返信(魔界の仮面弁士さんの記事)
回答ありがとうございます。

> > MainFormのロード直後に、Form1,2をロードすれば良いのですが、
> 本来なら、Application.Run に(Formではなく)ApplicationContext を
> 渡したたい所なのですが、Compact Framework では非サポートなんですよね…。
私のレベルではまだ理解できるところにはありません。もの凄く勉強が必要なようです。


>>また、MainFormをロードした時しか、Form1,2を2つロードする
>>ことはありません。
> 3 つのフォームを同時に表示させなければいけないのでしょうか?
私の技量の問題で、スマートデバイス的な作り方が出来ていないのかと思います。
今、行っていることは、MainFormでは、
対CFカード用のシリアル通信。
対サーバ用FTP通信。
取得した詳細データ表示画面の呼び出し。
各通信用パラメータ設定画面の呼び出し。
ID入力画面の呼び出し。
メニュー選択画面の呼び出し。

等を処理しています。
CFカードから受け取った詳細データを表示する画面(他Form)やシリアル通信、FTP通信のパラメータ設定を行う画面(他Form)をMainFormから呼び出します。

初回起動時に、操作者のIDを入力する画面とメニュー画面を開き、ID選択--->メニュー選択--->メイン画面に戻るということをしたくて、最初から2つ起動してしまえば、消すだけというイメージで同時に起動しています。

> Pocket PC 系の OS の場合、各フォーム(ダイアログを除く)は、
> http://msdn.microsoft.com/library/ja/jpdnnetcomp/html/NetCompactFrameWorkFAQ.asp
> の 4.8 にもあるように、一つのフォームが、画面いっぱいに表示されるのが
> 基本だと思いますので、複数表示させるなら、親子関係を持ったモーダル
> あるいはモードレスのダイアログにする事になると思いますが、各フォームの
> BorderStyle は、どのように設定されているのでしょうか?

今、現在は、全てFormBorderStyleは、FixedSingleになっています。
■No15058に返信(No.8さんの記事)
> ■No15054に返信(魔界の仮面弁士さんの記事)
> 回答ありがとうございます。

追記です。
いろいろ、書きましたが、3つのフォームを同時に開く=同時に使用するということはありません。
1画面が1つの操作者間のインターフェースを行う為、画面的には1つずつ開いていることでも一考に構わないのですが、メインからメイン以外の画面を起動するということで考えていた為、初回起動時のみ、メイン画面からForm1とForm2を起動してForm1--->Form2--->MainFormの順で操作していくとメイン画面まで戻れるという構成を考えておりました。
2006/03/28(Tue) 09:43:38 編集(投稿者)

■No15055に返信(No.8さんの記事)

おはようございます。

> Activateイベント内でTimerを起動して、時間を稼ぐ方法で考えてみます。

MainForm が表示されてから Form1,2 を表示で、解決するのであれば
MainForm内のLoad内にForm1,2の起動を記述しないで、MainFormのLoadを完了
させます。アイドル状態になればイベントを発生させ(Application.Idle)
そのタイミングでForm1,2を起動させれば、Timer起動より効率的と思います。
■No15064に返信(エツさんの記事)
> 2006/03/28(Tue) 09:43:38 編集(投稿者)
>
> ■No15055に返信(No.8さんの記事)
>
> おはようございます。
おはようございます。
回答ありがとうございます。

>>Activateイベント内でTimerを起動して、時間を稼ぐ方法で考えてみます。
>
> MainForm が表示されてから Form1,2 を表示で、解決するのであれば
> MainForm内のLoad内にForm1,2の起動を記述しないで、MainFormのLoadを完了
> させます。アイドル状態になればイベントを発生させ(Application.Idle)
> そのタイミングでForm1,2を起動させれば、Timer起動より効率的と思います。

ヘルプを見てCompact Frameworkは対象外のようでした。
確認として、Private WithEvents AppClass As Application としてみましたが
AppClassでイベントを選択できませんでした。

しかしながら、そういった方法があることが解りました。勉強になります。
ありがとうございました。
以下、VB2005でのPocket PC 開発は未経験なので、VB.NET 2003 や eVB3 での
知識を元に書いています。もしかしたらVB2005に当てはまらない部分もあるかも。m(_ _)m

>> 本来なら、Application.Run に(Formではなく)ApplicationContext を
>> 渡したたい所なのですが、Compact Framework では非サポートなんですよね…。
> 私のレベルではまだ理解できるところにはありません。もの凄く勉強が必要なようです。
ApplicationContext は、たとえば、複数のフォームを同時に開く必要がある場合
(メインフォームのような親子関係が無い場合)などに使われたりします。
ただ、あくまでも .NET Framework の Windows Application の世界の話なので、
現行の .NET Compact Framework においては、忘れてもらって構わないかと。


> いろいろ、書きましたが、3つのフォームを同時に開く=同時に使用するということはありません。
同時に使用する必要が無いのであれば、各フォームを同時に「表示」する
必要は無い気がします。だとすれば、MainForm の Load で「Show」せずとも、

(1) 各フォームが必要になった時点で、生成と表示を行う。
(2) 各フォームのインスタンスを生成するだけで、表示はしないでおく。
 (Sub MainやSub MainForm_Loadではインスタンス生成だけを行う)

などで対応できないでしょうか。たとえば
> FTP通信のパラメータ設定を行う画面(他Form)
そういった画面は、常時表示するというものではなく、設定を行っている間しか
使わないでしょうから、モードレス(Show)ではなく、モーダル(ShowDialog)で
使った方が都合が良いかもしれません。


> 操作者のIDを入力する画面とメニュー画面を開き、
> ID選択--->メニュー選択--->メイン画面に戻るということをしたくて
それならば、
 Public Sub Main()
  Using F As New ID選択フォーム()
   If F.ShowDialog() = DialogResult.OK Then
    Application.Run(New メインフォーム())
   End If
  End Using
 End Sub
のようなイメージになるのでは無いでしょうか。
# 手元に Compact Framework 2.0 環境が無いので、検証できませんけど。



> タイトル部分はMainForm名が表示され、画面をタップした時点で
> 漸くForm2のタイトルが表示されます。
このあたりは、デバイス側の性能にもよる所があるのかも知れません。
最初のコードを、Compact Framework 1.0 / PPC 2002 機で試したところ、
タイトル部分がそのような動きをする事はありませんでしたので。

もっとも、1.0環境で動かすために、Activate や TopMost の指定を
取り除いていたりするので、あまり参考にはならないのですけれども。(^^;
■No15066に返信(魔界の仮面弁士さんの記事)
回答ありがとうございます。

> 以下、VB2005でのPocket PC 開発は未経験なので、VB.NET 2003 や eVB3 での
> 知識を元に書いています。もしかしたらVB2005に当てはまらない部分もあるかも。m(_ _)m

> ApplicationContext は、たとえば、複数のフォームを同時に開く必要がある場合
> (メインフォームのような親子関係が無い場合)などに使われたりします。
> ただ、あくまでも .NET Framework の Windows Application の世界の話なので、
> 現行の .NET Compact Framework においては、忘れてもらって構わないかと。
そういったこともできるということが判りました。
ありがとうございます。

>>いろいろ、書きましたが、3つのフォームを同時に開く=同時に使用するということはありません。
> 同時に使用する必要が無いのであれば、各フォームを同時に「表示」する
> 必要は無い気がします。だとすれば、MainForm の Load で「Show」せずとも、
>
> (1) 各フォームが必要になった時点で、生成と表示を行う。
> (2) 各フォームのインスタンスを生成するだけで、表示はしないでおく。
>  (Sub MainやSub MainForm_Loadではインスタンス生成だけを行う)
>
> などで対応できないでしょうか。たとえば
>>FTP通信のパラメータ設定を行う画面(他Form)
> そういった画面は、常時表示するというものではなく、設定を行っている間しか
> 使わないでしょうから、モードレス(Show)ではなく、モーダル(ShowDialog)で
> 使った方が都合が良いかもしれません。

ご指摘の通り、FTP通信のパラメータ設定画面やシリアル設定画面は、通信中は
切り替えられないのでどちらも通信が行えなくなった状態で表示するつもりな
ので、一部の画面ではモーダル(ShowDialog)に設定することができそうです。

Showとしている理由は、モーダル画面を表示中は、他の処理が停止状態になると
いう認識でおり、残りがShowしかないという状況です。
また、ID入力画面、メニュー画面、バージョン情報等は、特にFTP通信中であって
も呼び出しが可能な構成にしたい為、モーダルで停止したことによる通信異常を
避けようと考え、Showする方法で考えておりました(異常となるかも知れないと
いう予測)。

一度切断して再接続という方法も考えましたが、操作者がちょっとした待ち時間
が煩わしいという意見があり、特にFTP通信したままでもID/メニューを切り替え
たいという考えです。

>>操作者のIDを入力する画面とメニュー画面を開き、
>>ID選択--->メニュー選択--->メイン画面に戻るということをしたくて
> それならば、
>  Public Sub Main()
>   Using F As New ID選択フォーム()
>    If F.ShowDialog() = DialogResult.OK Then
>     Application.Run(New メインフォーム())
>    End If
>   End Using
>  End Sub
> のようなイメージになるのでは無いでしょうか。
> # 手元に Compact Framework 2.0 環境が無いので、検証できませんけど。
>
Using ということを初めて知りました。早速試してみます。
モーダルでも裏(スレッド?)で通信が可能であれば、モーダルに変更してみ
ます。

>>タイトル部分はMainForm名が表示され、画面をタップした時点で
>>漸くForm2のタイトルが表示されます。
> このあたりは、デバイス側の性能にもよる所があるのかも知れません。
Genio830wと、もう1つは専用のターミナルでるがどちらもその事象となりまし
た。デバイスに依存することもあるのですね。
勉強になります。

丁寧な回答を頂きましてありがとうございます。
初めて間もないことと、VB2005の本とかまだ出ていないのでヘルプを見て動か
しては直すという繰り返しで、的を得た調べ方なのかも、まだまだ解っていな
い状況です。
まず、スレッドとモーダレスについて調べてみます。
また、質問すると思いますが宜しくお願い致します。
■No15065に返信(No.8さんの記事)

こんにちは

>>MainForm が表示されてから Form1,2 を表示で、解決するのであれば
>>MainForm内のLoad内にForm1,2の起動を記述しないで、MainFormのLoadを完了
>>させます。アイドル状態になればイベントを発生させ(Application.Idle)
>>そのタイミングでForm1,2を起動させれば、Timer起動より効率的と思います。
>
> ヘルプを見てCompact Frameworkは対象外のようでした。
> 確認として、Private WithEvents AppClass As Application としてみましたが
> AppClassでイベントを選択できませんでした。
>

私はVS2002なので的外れかもしれません。私の環境では
Private WithEvents AppClass As Application はコンパイルエラーになります。
ですから御参考までに私が使っているコードを書いてみます。

Loadの最後に次のようにイベント発生させるコードを書きます。

AddHandler Application.Idle, AddressOf Form発生



イベント発生時のメッソドは次のようになります。

Private Sub Form発生(ByVal sender As System.Object, ByVal e As System.EventArgs)

RemoveHandler Application.Idle, AddressOf Form発生

    フォームの起動処理プログラムを書く

End Sub

宜しければ試して下さい。
■No15071に返信(エツさんの記事)
> ■No15065に返信(No.8さんの記事)
>
> こんにちは

こんにちわ。
返信遅くなりまして失礼致しました。
また、丁寧にコードまで乗せて頂き、ありがとうございます。

> 私はVS2002なので的外れかもしれません。私の環境では
> Private WithEvents AppClass As Application はコンパイルエラーになります。
> ですから御参考までに私が使っているコードを書いてみます。
>
> Loadの最後に次のようにイベント発生させるコードを書きます。
>
> AddHandler Application.Idle, AddressOf Form発生
私の環境では、Application.Idle Idleで下線(波線)となり
'idle' は 'System.Windows.Forms.Application' のイベントではありません。
ということになりました。

やはり、Compact Framework2.0(1.0/1.1については不明)ではサポートされて
いないようです。

再度ヘルプを見て確認してみます。ありがとうございました。
■No15074に返信(No.8さんの記事)
この質問について、解決済みチェックが未チェックのままであった為、
投稿しております。

最終的にはActivatedイベントで初回フラグを見てタイマーを起動し、タイマー
イベント内で2つのフォームを起動することで解決致しました。

#板よごして申し訳ありません。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板