tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトル画面遷移
記事No11468
投稿日: 2015/08/12(Wed) 11:46
投稿者貴将
お世話になっています。
宜しくお願い致します。

環境
WINDOWS8
VB.NET 2013
i7
メモリー:8メガ


やりたいこと
@A.exeを起動
AAの画面のボタンを押下する ⇒B.exeを起動する
BBの画面が表示する
CB画面のボタン選択を押下する  ⇒C画面を表示
DC画面のボタン選択を押下する  ⇒D画面を表示
ED画面のボタン選択を押下する  ⇒E画面を表示


D画面
C画面
B画面
Aメニュー画面
このように一番上に、D画面を一番上に表示


C画面はパターン10通りありまして、画面内の総項目数が画面により200から3000個
D画面はパターン15通りありまして、画面内の総項目数が画面により200から5000個

現象が発生してしまうのは、項目数が多い画面で発生してしまいます。
発生しないときもあります。



現象
パターン1
C画面表示中に、画面が入れ替わってしまう。
パターン2
C画面表示中に、C⇒B⇒A⇒C・・・と延々に入れ替わってしまいます。
パターン3
D画面表示中に、画面が入れ替わってしまう。
パターン4
D画面表示中に、C⇒B⇒A⇒D⇒C⇒B⇒A⇒D・・・・ 
と延々に入れ替わってしまいます。(昼休み一時間ほど実行)


下記の対策を行いましたが駄目でした。

・画面に親子関係を作成(B画面C画面D画面)
・Me.Activate = True
  Me.TopMost = True
  me.TopMost = FalseをShownに記載
 

以上
宜しくお願い致します。

[ツリー表示へ]
タイトルRe: 画面遷移
記事No11469
投稿日: 2015/08/12(Wed) 16:28
投稿者魔界の仮面弁士
> 下記の対策を行いましたが駄目でした。

あらかじめ、ForegroundLockTimeout を 0 にしておいては如何でしょうか?
具体的な手順は、KB886217 をご覧下さい。
http://support.microsoft.com/kb/886217/ja


なお、「SPI_GETFOREGROUNDLOCKTIMEOUT」を使うことで、
一時的にこのパラメーターを変更することもできます。

[ツリー表示へ]
タイトルRe^2: 画面遷移
記事No11473
投稿日: 2015/08/17(Mon) 14:04
投稿者貴将
ありがとうございます。
返事が遅くなりすみません。

1番目の案は、いろいろと許可申請等の問題があり保留となり
2番目の案「SPI_GETFOREGROUNDLOCKTIMEOUT」を組込み実行しました。

数回実行したのですが、以前とかわらずダメでした。
1. 元の値を退避しておくで(oldValueの値)を確認したのですが
常に0でした。

下記にソースを記載します。

Imports System.Runtime.InteropServices

Public Class frmD

    Private Declare Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoW" _
          (ByVal uiAction As UInteger, _
           ByVal uiParam As UInteger, _
           ByRef pvParam As UInteger, _
           ByVal fWinIni As UInteger) As Boolean

    Dim oldValue As UInteger

    Private Const SPI_GETFOREGROUNDLOCKTIMEOUT As UInteger = &H2000
    Private Const SPI_SETFOREGROUNDLOCKTIMEOUT As UInteger = &H2001
    :
    :
    :
    :
    Private Sub frmD_Load(sender As Object, e As EventArgs) Handles Me.Load
        On Error Resume Next

        Me.SuspendLayout()
        Me.DoubleBuffered = True

        'カーソルを砂時計
        System.Windows.Forms.Cursor.Current = Cursors.WaitCursor

        ' 1. 元の値を退避しておく
        SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0UI, oldValue, 0UI)

        ' 2. ForegroundLockTimeoutを0に書き換える
        SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0UI, 0UI, 0UI)

        Me.Activate()
        Me.TopMost = True
    :
    :
    画面表示処理
    :
    :
   End Sub

    Private Sub frmD_Shown(sender As Object, e As EventArgs) Handles Me.Shown

        SplitContainer1.Panel1.VerticalScroll.Value = 0
        SplitContainer1.Panel1.HorizontalScroll.Value = 0
        SplitContainer1.Panel1.Update()

        SplitContainer1.Panel1.VerticalScroll.Value = 0
        SplitContainer1.Panel1.HorizontalScroll.Value = 0
        SplitContainer1.Panel1.Update()

        Me.Activate()
        Me.TopMost = True
        Me.TopMost = False

        ' 3. 元に戻す
        SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0UI, oldValue, 0UI)
        'カーソルをデフォルト
        System.Windows.Forms.Cursor.Current = Cursors.Default
        Me.ResumeLayout(False)
    End Sub
     :
    :
    :
    :

    
End Class

以上

[ツリー表示へ]
タイトルRe^3: 画面遷移
記事No11474
投稿日: 2015/08/18(Tue) 00:37
投稿者魔界の仮面弁士
> 1番目の案は、いろいろと許可申請等の問題があり保留となり
> 2番目の案「SPI_GETFOREGROUNDLOCKTIMEOUT」を組込み実行しました。

保留かどうかはさておき、1番目の方法で解決できるかどうかの検証さえも
実施することができないのでしょうか。

今回の現象が1番目の件が原因ではなかった場合、2番目の方法は
意味をなさないので、組み込んでも無駄になってしまうかと思いますよ。

(そもそも、最初の「延々に入れ替わってしまう」という説明が
 どういう状況を示しているのか、動作イメージが連想できないです…)


で、私の ForegroundLockTimeout 案は、「起動ウィンドウが手前に表示されない」
という状況を改善するためのものです。つまり、外部アプリケーションが対象なので、
提示頂いたコードだと、呼び出すべき個所が違っているように思えます。

なお当方では、ForegroundLockTimeout の修正によって、
「A.EXE から B.EXE を起動したときに、B が A の背後に表示されてしまう状況」
を改善することができています。
(実際に試したときは、A 側は *.HTA で、B は Excel.exe でした)



> 下記にソースを記載します。
パラメーターの指定が間違っているようです。

SPI_GETFOREGROUNDLOCKTIMEOUT の pvParam は LPDWORD ですが、
SPI_SETFOREGROUNDLOCKTIMEOUT の pvParam は DWORD ですよ。


[VB.NET / C# 版]
http://dobon.net/vb/dotnet/process/appactivate.html

[VB6版]
http://www.vb-user.net/yaplog/Source/SetForegroundWindow.txt

下記は、指定したウィンドウ(別プロセスのウィンドウを想定)を
フォアグラウンドにし、そのウィンドウを強制的にアクティブにするというものです。
SetForegroundWindow を呼ぶ前に、AttachThreadInput するのが肝ですが、
これについては AllowSetForegroundWindow の方が良いかもしれません。


> 1. 元の値を退避しておくで(oldValueの値)を確認したのですが
> 常に0でした。
API の呼び出しが間違っていることで、既に値が破壊されている可能性もあります。

以下、やや複雑な話ですが、参考情報として:
http://bbs.wankuma.com/index.cgi?mode=al2&namber=63230&KLOG=107

[ツリー表示へ]
タイトルRe^4: 画面遷移
記事No11475
投稿日: 2015/08/18(Tue) 15:53
投稿者貴将
ありがとうございます。

すみません。
説明不足でした。

構成
A.exe
・ログイン画面
・全体メニュー画面
B.exe
・Bメニュー画面
・C画面
・D画面
・E画面


・A画面⇒B画面⇒C画面
 ここまでは、表示で逆転現象は、100%発生していません。
>>保留かどうかはさておき、1番目の方法で解決できるかどうかの検証さえも
>>実施することができないのでしょうか。
とりあえず、対策の一環として、テストマシンの環境に入れさせて頂きました。



通常は
・A画面⇒B画面⇒C画面⇒D画面⇒E画面と正常時は、画面がつみあがります。

 同じ画面を開いても、現象が100%出るのではなく、出るときは、連続して発生します
 出ないときは、2時間くらい連続で動かしても現象が発生しません

 出やすいところは、画面項目数が多いとき、発生しやすいです
・B画面からC画面を選択し、さらに、D画面を選択したときに発生パターン
・B画面からC画面を選択し、さらに、D画面を選択しさらにE画面時を選択したときに発生パターン


 現在確認しているパターンは、3通り*2画面(D画面・E画面)です。


 パターン1:
  画面を開いていき、C画面からD画面を開いたとき、D画面を動的に作成し、
  表示中(Shownあたり)で、D画面の上にC画面が上に表示されてしまう


 パターン2:
  画面を開いていき、C画面からD画面を開いたとき、D画面を動的に作成し、
  D画面の上にC画面が上に表示されてD画面の処理で最終的にはD画面が一番上になる
  (上段の対策として、SHOWNに一番上への対策)


 パターン3:
  画面の切替が勝手に行われてしまう(画面は作成途中)
  D画面の表示時

    最背画面        最前画面 
    @A画面⇒B画面⇒C画面⇒D画面
    AB画面⇒C画面⇒A画面⇒D画面
    BD画面⇒B画面⇒C画面⇒A画面
    CA画面⇒D画面⇒B画面⇒C画面
    DC画面⇒A画面⇒D画面⇒B画面
          繰り返し(ループ)

   E画面の表示時
    最背画面            最前画面 
    @A画面⇒B画面⇒C画面⇒D画面⇒E画面
    AE画面⇒B画面⇒C画面⇒A画面⇒D画面
    BD画面⇒E画面⇒B画面⇒C画面⇒A画面
    CA画面⇒D画面⇒E画面⇒B画面⇒C画面
    DC画面⇒A画面⇒D画面⇒E画面⇒B画面
    EB画面⇒C画面⇒A画面⇒D画面⇒E画面
            繰り返し(ループ)
            



  現在対策として
 対策1:
   ShowDialogで画面を開いていましたが、Showに変更
            ⇒パターン3は、現在発生していません
 対策2:
   パターン2は、パターン1の対策として
   SHOWNに
           Me.Activate()
           Me.TopMost = True
           Me.TopMost = False
       を追加   ⇒ 100%聞くのではなくたまに聞く程度です。
       ⇒100%この対策できくなら問題ないのですが、きかないパターンもあります 

以上

[ツリー表示へ]
タイトルRe^5: 画面遷移
記事No11476
投稿日: 2015/08/19(Wed) 10:42
投稿者魔界の仮面弁士
> 同じ画面を開いても、現象が100%出るのではなく、出るときは、連続して発生します
これは、GUIのテスト自動化ライブラリ(Codeer.Friendly とか)を利用した上での検証結果でしょうか。
それとも、利用者による体験あるいは手動テストによるものでしょうか。

(再現したときの手順が、前回と同様の操作であったことを保証できれば良いのですが)


> ・A画面⇒B画面⇒C画面
> ここまでは、表示で逆転現象は、100%発生していません。
ここは問題無さそうなのですね。
[A.EXE]から[B.EXE]への起動は、Process.Start メソッドでしょうか。


>  画面を開いていき、C画面からD画面を開いたとき、
フォームの表示方法は、どのようにしていますか?

A: Form2.Show()    '暗黙のインスタンスを利用

B: Form2.Show(Me)  '暗黙のインスタンスを利用し、親フォームを明示

C: F = New Form2()
   F.Show()        '明示的インスタンスを利用

C: F = New Form2()
   F.Show(Me)      '明示的インスタンスを利用し、親フォームを明示

D: Using F As New Form2()
      F.ShowDialog()
   End Using       '明示的インスタンスを利用したモーダル表示

E: Using F As New Form2()
      F.ShowDialog(Me)
   End Using       '明示的インスタンスを利用し、親フォームを明示してモーダル表示

F: 上記以外




> D画面を動的に作成し、
D画面をデザイン時に用意しておくのではなく、コード上で動的に作成するということでしょうか?


Dim f As New Form()
f.Text = "動的生成"
Dim flow As New FlowLayoutPanel() With {.Dock = DockStyle.Fill, .AutoScroll = True}
flow.Controls.AddRange(Enumerable.Range(100, 200).Select(
    Function(i) New TextBox() With {.Text = CStr(i)}).ToArray())
f.Controls.Add(flow)
AddHandler f.FormClosing, Sub(o, p) MsgBox("合計値:" &
    flow.Controls.OfType(Of TextBox)().Sum(Function(t) Val(t.Text)))
f.Show(Me)



>  表示中(Shownあたり)で、
Shown は表示中ではなく、表示直後ですね。


> D画面の上にC画面が上に表示されてしまう
D は C の子画面なのでしょうか?

オーナー指定があるのに、親子関係が変わってしまうのだとしたら問題ですが、
オーナー指定が無いのなら、どちらが手前にもなりえるはずです。
(表示されるタイミングが適切かどうかは別ですが)


> 出やすいところは、画面項目数が多いとき、発生しやすいです
・処理に長い時間(たとえば1秒以上)を要するイベントがありませんか?
・DoEvents を呼び出している箇所はありませんか?
・BringToFront/SendToBack/Activate などを意図的に呼び出しているイベントはありませんか?
・暗黙のフォームインスタンスを利用していませんか?



> 画面の切替が勝手に行われてしまう(画面は作成途中)
ユーザーが何も操作していないのに、一定時間あるいは不定期に
前面表示の切り替わりが起こってしまう、ということでしょうか?

それとも、特定の操作をしたときに、意図しない画面の切替が
発生しはじめるということでしょうか。


Activated や Deactivate で他のフォームを制御していたり、
意図的に TopMost の On/Off 切替を行っているようなコードが
どこかに紛れているような気もしますが…そういうわけでは無いのでしょうし。


「現象を再現可能なテストアプリ」を作ることが難しいなら、
既存のコードを削っていき、どの処理を通過したときに
現象が発生しているのかの特定が必要になりそうですが、
こればっかりは、ソースコードを持っている当人でなければ
判断できないですしね…。

[ツリー表示へ]
タイトルRe^6: 画面遷移
記事No11477
投稿日: 2015/08/20(Thu) 23:20
投稿者貴将
ありがとうございます。
遅くなりすみません。

> > 同じ画面を開いても、現象が100%出るのではなく、出るときは、連続して発生します
> これは、GUIのテスト自動化ライブラリ(Codeer.Friendly とか)を利用した上での検証結果でしょうか。
> それとも、利用者による体験あるいは手動テストによるものでしょうか。
>
> (再現したときの手順が、前回と同様の操作であったことを保証できれば良いのですが)
>

  ⇒ 回答
  
    手動テストによるものです。
    
    ⇒C画面からD画面を表示するときは、C画面上のラベルをクリック(動的ラベル)
    ⇒D画面からE画面を表示するときは、D画面上のボタンをクリック(動的ボタン)


>
> > ・A画面⇒B画面⇒C画面
> > ここまでは、表示で逆転現象は、100%発生していません。
> ここは問題無さそうなのですね。
> [A.EXE]から[B.EXE]への起動は、Process.Start メソッドでしょうか。
  ⇒ 回答
    
    はい
>
>
> >  画面を開いていき、C画面からD画面を開いたとき、
> フォームの表示方法は、どのようにしていますか?
>
> A: Form2.Show()    '暗黙のインスタンスを利用
>
> B: Form2.Show(Me)  '暗黙のインスタンスを利用し、親フォームを明示
>
> C: F = New Form2()
>    F.Show()        '明示的インスタンスを利用
>
> C: F = New Form2()
>    F.Show(Me)      '明示的インスタンスを利用し、親フォームを明示
>
> D: Using F As New Form2()
>       F.ShowDialog()
>    End Using       '明示的インスタンスを利用したモーダル表示
>
> E: Using F As New Form2()
>       F.ShowDialog(Me)
>    End Using       '明示的インスタンスを利用し、親フォームを明示してモーダル表示
>
> F: 上記以外
>
  ⇒ 回答
    現在は、現象が少ないAのパターンを採用しています。

    過去に Cのパターン、Bのパターン、及びForm2.ShowDialog等を行いました。
    (ShowDialogはBやCのパターン行い、Usingは使用していません)
    ⇒  頻繁に現象が発生しました。
  
  
>
>
>
> > D画面を動的に作成し、
> D画面をデザイン時に用意しておくのではなく、コード上で動的に作成するということでしょうか?
>

  ⇒回答
    すみません。説明不足で補足します。
    
    
    C画面 
      デザイン時
       @フォーム上に、ピクチャーボックスを作成
        ⇒ピクチャーボックスには、JPGのイメージを設定
        ⇒InitialImage ⇒ ローカルリリースを選択してインポートしています(JPG)
       Aフォーム上に、ボタンを作成(印刷・終了)
      動的
       @ピクチャーボックスのイメージ上(下絵)に、ラベルを動的に作成します。
        ⇒・動的にラベルを作成します
         ・ラベルのバックカラーを条件によって変えます
         ・ラベルの大きさを条件によって変えます
         ・ラベルにクリックイベントを追加します

    D画面 
      デザイン時
       @フォームをsplitcontainerで上下に分割
       A上の段にピクチャーボックスを作成、
       B下の段にボタンを作成(印刷・終了)
      動的
       @ピクチャーボックスに動的にボタンを追加します。
        2から20個までパターンがあります
       Aラベルを作成します
         ・100から1500個くらいのラベルを作成します
         ・ラベルのバックカラーを条件によって変えます

    E画面 
      デザイン時
       @フォームをsplitcontainerで上下に分割
       A上の段にピクチャーボックスを作成、
       B下の段にボタンを作成(印刷・終了)
      動的
       @ラベルを作成します
         ・500から6000個くらいのラベルを作成します
         ・ラベルのバックカラーを条件によって変えます







    C画面からD画面を表示するときは、動的に作成したラベルをクリックします。
    D画面からE画面を表示するときは、動的に作成したボタンをクリックします。
    

    動的の作成数
                         D画面    E画面
    A画面⇒B画面⇒C画面⇒D1画面⇒E11画面  300個        400個
                   ⇒E12画面  300個        400個
                D2画面⇒E21画面  300個        400個
                D3画面⇒E31画面  800個       1200個
                   ⇒E32画面  300個       1500個
                D4画面⇒E41画面   800個       2400個
                D5画面⇒E52画面  1000個       4000個
                D6画面⇒E63画面  1500個       6000個





>
> Dim f As New Form()
> f.Text = "動的生成"
> Dim flow As New FlowLayoutPanel() With {.Dock = DockStyle.Fill, .AutoScroll = True}
> flow.Controls.AddRange(Enumerable.Range(100, 200).Select(
>     Function(i) New TextBox() With {.Text = CStr(i)}).ToArray())
> f.Controls.Add(flow)
> AddHandler f.FormClosing, Sub(o, p) MsgBox("合計値:" &
>     flow.Controls.OfType(Of TextBox)().Sum(Function(t) Val(t.Text)))
> f.Show(Me)
>
>
   
    
>
>
> > D画面の上にC画面が表示されてしまう
> D は C の子画面なのでしょうか?

  ⇒回答
   Form2.Showで開いている画面です。
   


>
> オーナー指定があるのに、親子関係が変わってしまうのだとしたら問題ですが、
> オーナー指定が無いのなら、どちらが手前にもなりえるはずです。
> (表示されるタイミングが適切かどうかは別ですが)

>
> > 出やすいところは、画面項目数が多いとき、発生しやすいです
> ・処理に長い時間(たとえば1秒以上)を要するイベントがありませんか?
  ⇒回答
    ・はい
     表示するのに一つ一つ出ているイメージです
     
> ・DoEvents を呼び出している箇所はありませんか?
  ⇒回答
    ・使用していません。
    
> ・BringToFront/SendToBack/Activate などを意図的に呼び出しているイベントはありませんか?
  ⇒回答
    ・はい(ShownでActivateを使用しています。)
> ・暗黙のフォームインスタンスを利用していませんか?
  ⇒回答
    ・はい
     ⇒明示的インスタンスを利用して動かすと頻繁に問題が発生します。


>
>
>
> > 画面の切替が勝手に行われてしまう(画面は作成途中)
> ユーザーが何も操作していないのに、一定時間あるいは不定期に
> 前面表示の切り替わりが起こってしまう、ということでしょうか?
>
> それとも、特定の操作をしたときに、意図しない画面の切替が
> 発生しはじめるということでしょうか。
>
  ⇒回答
    クリックしてから画面が表示される間です
    
    C画面からD画面を表示するときは、動的に作成したラベルをクリックしたあと
    
    
    D画面からE画面を表示するときは、動的に作成したボタンをクリックしたあと
    
    


>
> Activated や Deactivate で他のフォームを制御していたり、
> 意図的に TopMost の On/Off 切替を行っているようなコードが
> どこかに紛れているような気もしますが…そういうわけでは無いのでしょうし。
  ⇒回答
    ・はい(ShownでActivate及びTopMostを使用しています。)

[ツリー表示へ]
タイトルRe^7: 画面遷移
記事No11478
投稿日: 2015/08/21(Fri) 10:44
投稿者魔界の仮面弁士
> (ShowDialogはBやCのパターン行い、Usingは使用していません)
Using を使うかどうかは任意ですが、その場合は「Dispose」が必要です。


Show の場合、フォームが閉じられたときに、自動的に Dispose されるため不要ですが、
ShowDialog した場合は、Close してもインスタンスは破棄されません。非表示になるだけです。

hhttps://msdn.microsoft.com/ja-jp/library/c7ykbedk.aspx
》 ダイアログ ボックスとして表示されているフォームは閉じられるのではなく非表示になるため、
》 フォームがアプリケーションで不要になった場合は、そのフォームの Dispose メソッドを
》 呼び出す必要があります。

各フォームの連携部分で、上記の違いは認識されていますでしょうか?


> 現在は、現象が少ないAのパターンを採用しています。
> 過去に Cのパターン、Bのパターン、及びForm2.ShowDialog等を行いました。

暗黙のフォームを使った場合、インスタンスの管理が曖昧になるため、
閉じたフォームが再生成されて開かれたのか、
非表示だったフォームが再表示されたのか、分かり難くなります。

そのためコーディングミスにより、以前とは違うインスタンスを操作することで
意図せぬ画面遷移が行われてしまっているケースを見かけます。


たとえば、これは極端な例ですが
 ・モードレスなサブ画面を表示中は、呼びだし元のメイン画面を消す
 ・サブ画面が閉じたら、呼びだし元の画面を再表示する
という処理を実装するにあたり、下記のような処理になっていることがありました。


'アプリケーション設定:シャットダウンモード=「最後のフォームが閉じるとき」
Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Form2.Show()
        Me.Hide()
    End Sub
    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        Form2.Show()
        Me.Close()
    End Sub
End Class
Public Class Form2
    Private Sub Form2_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
        Form1.Show()
    End Sub
End Class


この場合、Button1 と Button2 は明らかに違う意味を持つのですが、
各フォームの表示位置やサイズが固定化されていたため(というか最大化)、
実行時テストでは、両者のその違いに気付かなかったのだそうです。

(上記の場合、Hide と Close の違いが争点ではありますが、それとは別に
Form2 内から、Form1 という暗黙インスタンスを操作していることも問題です)



> ⇒InitialImage ⇒ ローカルリリースを選択してインポートしています(JPG)
Local Release …というのは、
Local Resource のことでしょうか。


> ・500から6000個くらいのラベルを作成します
その数になると、Label で処理するよりも、Paint イベントあたりで
描画処理として片付けた方が、処理が軽くなるのではないでしょうか。
まぁ、実装の手間としては Label の方が楽なのかもしれませんけど。


> > D は C の子画面なのでしょうか?
>   ⇒回答
>    Form2.Showで開いている画面です。

Form2.Show したことと、それが子画面であるかどうかは無関係です。


Public Class Form2
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Form3.Show()
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        Form3.Owner = Me
        Form3.Show()
    End Sub

    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        Form3.Show(Me)
    End Sub
End Class


Button1 から呼び出した Form3 は、Form2 の子画面ではありませんが、
Button2 および 3 での Form3 は、Form2 の子画面です。動作の違いを確認してみてください。

・親画面が閉じられると、子画面も一緒に閉じられます。
・子画面は、常に親画面よりも手前に表示されます。

※ 身近な「子画面」の例としては、「メモ帳」における「検索」画面などがあります。


ただ、Button3 のパターンは過去に試していて、その場合は
『頻繁に現象が発生しました。』とのことでしたよね。それは、
Form2 が、Form3 よりも手前に来てしまう状態であったという意味でしょうか?



>> ・処理に長い時間(たとえば1秒以上)を要するイベントがありませんか?
>  ・はい
長い処理を UIスレッドで行うと、ウィンドウメッセージの流れを阻害してしまいます。
それらの処理を非同期処理として、ワーカースレッドで処理することを検討してみて下さい。


>> ・BringToFront/SendToBack/Activate などを意図的に呼び出しているイベントはありませんか?
>   ・はい(ShownでActivateを使用しています。)
Activate は、(自アプリ内における)アクティブフォームの切替を行うための物ですよね。

複数の画面が立ち上がっていて、特定のフォームを明示的にアクティブにしたいときに使うことはありますが、
Shown 時に呼び出すべきようなものではありません。使いどころを見直してみてください。




> > ・暗黙のフォームインスタンスを利用していませんか?
> >   ⇒回答
> >     ・はい
> >      ⇒明示的インスタンスを利用して動かすと頻繁に問題が発生します。
同じフォームを複数開くことがないのであれば、暗黙でも明示的でも構いませんが、
この場合の争点は、フォームの有効期間をきちんと把握しているか否かです。

きちんと管理されているなら、暗黙だろうと明示的だろうと、同じ動作になるはずですし、
暗黙か明示的かで動作に影響があるのなら、フォームの取り扱い方に問題があることになります。



>  クリックしてから画面が表示される間です
Shown で Activate するなど、あまり一般的では無いフォーカス制御を行っているようですし、
話を聞く限りでは、問題を解消しようとするために仕掛けた TopMost や Activate 等が、
余計に問題を複雑化させているようにみうけられます。
原因を特定しないまま対処療法を続けるのは、あまり得策では無いと思いますよ。

[ツリー表示へ]
タイトルRe^8: 画面遷移
記事No11480
投稿日: 2015/08/21(Fri) 18:09
投稿者貴将
ありがとうございます。



> > (ShowDialogはBやCのパターン行い、Usingは使用していません)
> Using を使うかどうかは任意ですが、その場合は「Dispose」が必要です。
>
>
> Show の場合、フォームが閉じられたときに、自動的に Dispose されるため不要ですが、
> ShowDialog した場合は、Close してもインスタンスは破棄されません。非表示になるだけです。
>
> hhttps://msdn.microsoft.com/ja-jp/library/c7ykbedk.aspx
> 》 ダイアログ ボックスとして表示されているフォームは閉じられるのではなく非表示になるため、
> 》 フォームがアプリケーションで不要になった場合は、そのフォームの Dispose メソッドを
> 》 呼び出す必要があります。
>
> 各フォームの連携部分で、上記の違いは認識されていますでしょうか?
>
⇒返答
    はい
    たびたびすみません。
    もう少し補足を記載させて頂きます
    
    動的に作成
    A画面⇒B画面⇒C1画面⇒D1画面⇒E11画面  300個        400個
                   ⇒E12画面  300個        400個
                D2画面⇒E21画面  300個        400個
                D3画面⇒E31画面  800個       1200個
                   ⇒E32画面  300個       1500個
                D4画面⇒E41画面   800個       2400個
                D5画面⇒E52画面  1000個       4000個
                D6画面⇒E63画面  1500個       6000個 ← 今はここだけ
    デザインで作成
            C2画面⇒D7画面
            C3画面⇒D8画面⇒E81画面⇒F82画面
            C4画面⇒D9画面⇒E91画面
                D10画面

   問題が発生する前の考え方
   画面の遷移について
    @最前面の画面だけを使用する
    A画面の表示方式は次画面をShowDialog( 明示的インスタンスを利用 )

      F = New ew Form2()
      F.ShowDialog()
      F.Dispose
      作成方針でした。
      
      デザインだけで作成したソースは、問題なく動きます。
      項目数が多くデザインで対応できなかったものを動的に作成しました
      画面構成等が同じため⇒上段部分は動的に作成しました。
      
      
      
      動的に作成した画面 D6画面とE63画面を呼び出すときに問題が現在でも発生します。
      
      
      
         いろいろな組み合わせの結果
         ・一番問題がないパターンを使用しました。
          ⇒明示的インスタンスを使用して、動かすと頻繁に無限的に画面の切替問題が発生します。
          
          

>
> > 現在は、現象が少ないAのパターンを採用しています。
> > 過去に Cのパターン、Bのパターン、及びForm2.ShowDialog等を行いました。
>
> 暗黙のフォームを使った場合、インスタンスの管理が曖昧になるため、
> 閉じたフォームが再生成されて開かれたのか、
> 非表示だったフォームが再表示されたのか、分かり難くなります。
>
> そのためコーディングミスにより、以前とは違うインスタンスを操作することで
> 意図せぬ画面遷移が行われてしまっているケースを見かけます。
>
>
> たとえば、これは極端な例ですが
>  ・モードレスなサブ画面を表示中は、呼びだし元のメイン画面を消す
>  ・サブ画面が閉じたら、呼びだし元の画面を再表示する
> という処理を実装するにあたり、下記のような処理になっていることがありました。
>
>
> 'アプリケーション設定:シャットダウンモード=「最後のフォームが閉じるとき」
> Public Class Form1
>     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
>         Form2.Show()
>         Me.Hide()
>     End Sub
>     Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
>         Form2.Show()
>         Me.Close()
>     End Sub
> End Class
> Public Class Form2
>     Private Sub Form2_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
>         Form1.Show()
>     End Sub
> End Class
>
>
> この場合、Button1 と Button2 は明らかに違う意味を持つのですが、
> 各フォームの表示位置やサイズが固定化されていたため(というか最大化)、
> 実行時テストでは、両者のその違いに気付かなかったのだそうです。
>
> (上記の場合、Hide と Close の違いが争点ではありますが、それとは別に
>  Form2 内から、Form1 という暗黙インスタンスを操作していることも問題です)
>






>
>
> > ⇒InitialImage ⇒ ローカルリリースを選択してインポートしています(JPG)
> Local Release …というのは、
> Local Resource のことでしょうか。

⇒返答
  すみません 記載ミスでした。


>
>
> > ・500から6000個くらいのラベルを作成します
> その数になると、Label で処理するよりも、Paint イベントあたりで
> 描画処理として片付けた方が、処理が軽くなるのではないでしょうか。
> まぁ、実装の手間としては Label の方が楽なのかもしれませんけど。
>
>
> > > D は C の子画面なのでしょうか?
> >   ⇒回答
> >    Form2.Showで開いている画面です。
>
> Form2.Show したことと、それが子画面であるかどうかは無関係です。
>
>
> Public Class Form2
>     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
>         Form3.Show()
>     End Sub
>
>     Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
>         Form3.Owner = Me
>         Form3.Show()
>     End Sub
>
>     Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
>         Form3.Show(Me)
>     End Sub
> End Class
>
>
> Button1 から呼び出した Form3 は、Form2 の子画面ではありませんが、
> Button2 および 3 での Form3 は、Form2 の子画面です。動作の違いを確認してみてください。
>
> ・親画面が閉じられると、子画面も一緒に閉じられます。
> ・子画面は、常に親画面よりも手前に表示されます。
>
> ※ 身近な「子画面」の例としては、「メモ帳」における「検索」画面などがあります。
>
>
> ただ、Button3 のパターンは過去に試していて、その場合は
> 『頻繁に現象が発生しました。』とのことでしたよね。それは、
> Form2 が、Form3 よりも手前に来てしまう状態であったという意味でしょうか?
>

⇒返答
    はい、そうです。
    Button2 のパターンでも頻繁に現象が発生しました。
    
    



>
>
> >> ・処理に長い時間(たとえば1秒以上)を要するイベントがありませんか?
> >  ・はい
> 長い処理を UIスレッドで行うと、ウィンドウメッセージの流れを阻害してしまいます。
> それらの処理を非同期処理として、ワーカースレッドで処理することを検討してみて下さい。
>




⇒返答
    最後の画面描画の部部なので







>
> >> ・BringToFront/SendToBack/Activate などを意図的に呼び出しているイベントはありませんか?
> >   ・はい(ShownでActivateを使用しています。)
> Activate は、(自アプリ内における)アクティブフォームの切替を行うための物ですよね。
>
> 複数の画面が立ち上がっていて、特定のフォームを明示的にアクティブにしたいときに使うことはありますが、
> Shown 時に呼び出すべきようなものではありません。使いどころを見直してみてください。
>
>
>
>
> > > ・暗黙のフォームインスタンスを利用していませんか?
> > >   ⇒回答
> > >     ・はい
> > >      ⇒明示的インスタンスを利用して動かすと頻繁に問題が発生します。
> 同じフォームを複数開くことがないのであれば、暗黙でも明示的でも構いませんが、
> この場合の争点は、フォームの有効期間をきちんと把握しているか否かです。
>
> きちんと管理されているなら、暗黙だろうと明示的だろうと、同じ動作になるはずですし、
> 暗黙か明示的かで動作に影響があるのなら、フォームの取り扱い方に問題があることになります。
>
>
>
> >  クリックしてから画面が表示される間です
> Shown で Activate するなど、あまり一般的では無いフォーカス制御を行っているようですし、
> 話を聞く限りでは、問題を解消しようとするために仕掛けた TopMost や Activate 等が、
> 余計に問題を複雑化させているようにみうけられます。
> 原因を特定しないまま対処療法を続けるのは、あまり得策では無いと思いますよ。

⇒返答
    はい、できればとりたいのですが、
    入れても入れなくても問題は発生していますので
    
以上

[ツリー表示へ]