- PR -

フォームの表示順とフォーカスについて教えてください

投稿者投稿内容
MrKong
常連さん
会議室デビュー日: 2004/01/24
投稿数: 22
投稿日時: 2006-10-20 10:32
VB.NET2003で開発しているプログラムのフォーム表示と
フォーカスについて質問があります。
以下のような場合、
フォームの表示順とフォーカスはどうなるのが正解でしょうか?

1.AP1のSub Main()からShowDialogでForm1を開く。
2.Form1のLoadイベント内で、別スレッドThread1を実行。
3.Thread1内で別APであるAP2をプロセスオブジェクトのStartメソッド  
  (Proccess.Start)で実行。
  AP2が終了するまでobjProcess.WaitForExit()で待つ。
  ※AP2のフォームロードイベントにはTopMost=Trureの記述あり。

望んでいる動きは、
「Form1の上にフォーカスを持ったAP2のフォームが表示される」です。
現在、上記のような処理を行った場合、
ほとんどの場合上記の動きをしていますが、
たまにFrom1の下にAP2のフォームが隠れてしまうことがあります。
また、これもごくたまになのですが、AP2が上に表示されているにも関わらず、
フォーカスがForm1のままの場合もあります。

もし“望んでいる動き”を実現するためのお知恵をお持ちの方がおられましたら、
ぜひご教授をお願いします。
まどか
ぬし
会議室デビュー日: 2005/09/06
投稿数: 372
お住まい・勤務地: ますのすし管区
投稿日時: 2006-10-20 12:11
引用:

以下のような場合、
フォームの表示順とフォーカスはどうなるのが正解でしょうか?


別プロセスの起動タイミングとThreadの使用が理由で、正解はありません。

引用:

2.Form1のLoadイベント内で、別スレッドThread1を実行。


Loadは表示される直前に発生します。

引用:

3.Thread1内で別APであるAP2をプロセスオブジェクトのStartメソッド  
  (Proccess.Start)で実行。
  AP2が終了するまでobjProcess.WaitForExit()で待つ。
  ※AP2のフォームロードイベントにはTopMost=Trureの記述あり。


別プロセスを起動するのに、なぜThreadを使用するのですか?
単に起動すればよいだけだと思います。

引用:

望んでいる動きは、
「Form1の上にフォーカスを持ったAP2のフォームが表示される」です。
もし“望んでいる動き”を実現するためのお知恵をお持ちの方がおられましたら、
ぜひご教授をお願いします。


原因としては、
起動をLoadでおこなっているのでAP1がまだ入力待ちでないこと(フォーカス系のメッセージが完了していない)、
Threadを使用しているのでそのときのOSの負荷などにより処理時間等が不定であること
になります。

対処としては、AP2の起動をAP1が入力待ち、つまりLoad終了後にFormが完全に表示されてからおこなうということになるでしょう。
2003ということなので、Load直後のActivatedにて起動処理をすればよいと思います。
Load直後の判断は
・自前のフラグで制御
・ActivatedのHandles句を書かず、Loadの最終ステップでAddHandlerする
でできます。
ただし、相手が「別プロセス」ですので必ずうまくいくとは限らないかもしれません。
#あ、Formは最初非表示でAP2が終わったら表示するとか。
MrKong
常連さん
会議室デビュー日: 2004/01/24
投稿数: 22
投稿日時: 2006-10-20 13:51
まどか様、ご回答ありがとうありがとうございます。

なぜAP1からAP2をスレッドで起動しているかという点ですが、
AP1のForm1を表示しつつ、別の処理をしていく必要があるからです。
例えますと、
 AP1のForm1で画面上に文字スクロールを表示しつつ、
 別で内部計算処理を実行する
みたいな感じでしょうか。

上の例でいきますと、
・AP1の画面は起動から終了まで絶えずスクロールする必要がある
・同時に内部処理を行い、その過程でAP2を起動しなければならない
・AP2の画面はAP1より全面でかつフォーカスを持っていないといけない
(AP2は確認画面のようなものです)



それぞれのタイミングですが、
1.Sub Mainの最後でフォームをShowDialog。
2.form1のLoadイベントの最後でスレッド起動
3.スレッド処理の途中でAP2を起動
になります。

まどか
ぬし
会議室デビュー日: 2005/09/06
投稿数: 372
お住まい・勤務地: ますのすし管区
投稿日時: 2006-10-20 14:27
引用:

2.form1のLoadイベントの最後でスレッド起動


ですから、Load内ではまだ表示されてない(フォーカスが無い)ので
少なくとも表示された後(Activated)へ処理を移す必要があります。
#順番を意識しているのですから、その順番になるように実行する必要があります。

とはいうものの先に書いたように別プロセスとの絡みですので結果は保証できません。
#AP1,AP2だけの問題ではないので
終了を待機するということ以外で、別プロセスの動き(Windowsアプリケーションとしての動き)に依存することは避けるべきと考えます。

あと、ShowDialogする必要は無いと思いますが。。。>Application.Run(New Form1)
#フォーカスのみの矛盾はこれが原因かもしれません。
MrKong
常連さん
会議室デビュー日: 2004/01/24
投稿数: 22
投稿日時: 2006-10-20 15:16
まどか様、たびたびのご回答ありがとうございます。

ご指摘いただいたスレッドの起動タイミングや、
Showdialogあたりをちょっと検討してみようと思います。
コーディングの経緯が分からないので、
とりあえずいろいろ試そうと思います。

どうもありがとうございました。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2006-10-20 18:43
process.startって、すぐ帰ってくるんじゃなかった?
form.showも、すぐ帰ってくると思うけど?

なんでそんなコーディングになったのか、謎
_________________
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-10-20 20:36
引用:

Jittaさんの書き込み (2006-10-20 18:43) より:

process.startって、すぐ帰ってくるんじゃなかった?


そんなことはないと思いますよ。
すぐだとしても、別のスレッドの処理が入り込む余地は多いにあります。

本題の方ですが、概ねまどかさんの意見に同意です。
スレッドを使うことによって、どちらが先に実行されるかの保証がないこと、
Load イベントで処理しているところがおかしいですね。

ちなみに、正しい順番で実行されても、Active にならない場合があると思います。
このあたりは、強制的にアクティブになるようなコードを忍ばせておいた方が良いでしょう。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
MrKong
常連さん
会議室デビュー日: 2004/01/24
投稿数: 22
投稿日時: 2006-10-23 13:48
Jittaさま、じゃんむねっとさま、ご意見ありがとうございます。

まずは、LoadイベントをActivatedイベントに移し、
強制的にアクティブになるようなコードを入れる方向で検討中です。
実行順に保証がないというお話ですが、
実際に順序が入れ替わる(フォームの表示順が入れ替わる)現象って、
そんなに頻繁に起きてはいないんですよね。
2000ユーザ以上が週5日業務で使用しても、
月に1〜2回ある程度です。
なんとなく素人考えだと、
実行順が不定の場合 = 半々くらいの割合でどちらの現象も起きる
と考えがちですがそうでもないのですね。

スキルアップ/キャリアアップ(JOB@IT)