C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

マルチディスプレイでの子フォームの表示位置について

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■89969 / inTopicNo.1)  マルチディスプレイでの子フォームの表示位置について
  
□投稿者/ 粗品 (1回)-(2019/01/25(Fri) 13:33:41)

分類:[VB.NET/VB2005 以降] 

開発環境 VisualStudio2008 + VisualBasic + .Net Framework3.5 + Windows10 Pro 64bit

マルチディスプレイの環境での質問です
親フォームからモーダルで呼び出される子フォームのプログラムを作ろうとしています。

親フォームから子フォームを表示する時、子フォームの表示位置を親フォームの中央(CenterParent)に設定しています。
この時はプライマリ、セカンダリの画面のどちらに親フォームがあっても親のところに表示されます。

ところが子フォームを全画面表示(WindowState=Maximized)にして呼び出すようにすると
VisualStudioの開発環境からデバックの時はセカンダリ画面で子を呼び出すとセカンダリ画面に全画面表示されるのですが、
ビルドした実行ファイル(exe)で動かすとセカンダリ画面で呼び出した時、子はプライマリ画面で全画面表示されるのです。
この時、一旦通常ウィンドウに戻し、再度全画面表示すると正しくセカンダリ画面に全画面展開します。
(それ以降は正しく表示されるが、子を閉じて新たに開くと同じ現象)

何か対応策があるのか、そんなもんですよ
なのか

よろしくお願いいたします。

引用返信 編集キー/
■89970 / inTopicNo.2)  Re[1]: マルチディスプレイでの子フォームの表示位置について
□投稿者/ 魔界の仮面弁士 (2020回)-(2019/01/25(Fri) 13:54:06)
2019/01/25(Fri) 13:54:48 編集(投稿者)

No89969 (粗品 さん) に返信
> 開発環境 VisualStudio2008 + VisualBasic + .Net Framework3.5 + Windows10 Pro 64bit
同じ環境が手元に無いので、再現できてはいないのですが、
とりあえず思いつくところで。


> 親フォームからモーダルで呼び出される子フォームのプログラムを作ろうとしています。

Using 子 As New 子フォーム()
 子.ShowDialog(Me)
End Using

のように、ShowDialog メソッドの Owner 引数に
親フォームのインスタンスを渡していますか?


また、子フォームのインスタンスは、"既定のインスタンス" に
頼ったものではなく、自身で生成・管理しているものでしょうか。
引用返信 編集キー/
■89974 / inTopicNo.3)  Re[2]: マルチディスプレイでの子フォームの表示位置について
□投稿者/ 粗品 (2回)-(2019/01/25(Fri) 15:33:52)
No89970 (魔界の仮面弁士 さん) に返信
> Using 子 As New 子フォーム()
>  子.ShowDialog(Me)
> End Using
>
> のように、ShowDialog メソッドの Owner 引数に
> 親フォームのインスタンスを渡していますか?
>
>
> また、子フォームのインスタンスは、"既定のインスタンス" に
> 頼ったものではなく、自身で生成・管理しているものでしょうか。

呼び出し方は正にUsingを使って、子をShowDialog(Me)で表示しています


引用返信 編集キー/
■89990 / inTopicNo.4)  Re[1]: マルチディスプレイでの子フォームの表示位置について
□投稿者/ 魔界の仮面弁士 (2024回)-(2019/01/28(Mon) 18:14:12)
2019/01/28(Mon) 18:15:10 編集(投稿者)

No89969 (粗品 さん) に返信
> 開発環境 VisualStudio2008 + VisualBasic + .Net Framework3.5 + Windows10 Pro 64bit
> ビルドした実行ファイル(exe)で動かすとセカンダリ画面で呼び出した時、子はプライマリ画面で全画面表示されるのです。


再現手順が分かりました。

(1) プライマリモニタ上で exe を実行し、そのまま子フォームを表示 → ○プライマリ上で全画面
(2) セカンダリモニタ上で exe を実行し、そのまま子フォームを表示 → ○セカンダリ上で全画面
(3) プライマリモニタ上で exe を実行し、Form1 をセカンダリに移動してから子フォームを表示 → ×プライマリ上で全画面
(4) セカンダリモニタ上で exe を実行し、Form1 をプライマリに移動してから子フォームを表示 → ×セカンダリ上で全画面



とりあえず、コンストラクタ(というか InitializeComponent)の段階では Maximized を解除しておき、
Load イベントの中で Maximized をセットすれば回避されるようです。


 Using childForm As New Form() With {.StartPosition = FormStartPosition.CenterParent}
   childForm.WindowState = FormWindowState.Normal
   AddHandler childForm.Load, Sub() childForm.WindowState = FormWindowState.Maximized
   childForm.ShowDialog(Me)
 End Using
引用返信 編集キー/
■89996 / inTopicNo.5)  Re[2]: マルチディスプレイでの子フォームの表示位置について
□投稿者/ 魔界の仮面弁士 (2028回)-(2019/01/29(Tue) 09:49:27)
No89990 (魔界の仮面弁士) に追記
> 再現手順が分かりました。
> (3) プライマリモニタ上で exe を実行し、Form1 をセカンダリに移動してから子フォームを表示 → ×プライマリ上で全画面
> (4) セカンダリモニタ上で exe を実行し、Form1 をプライマリに移動してから子フォームを表示 → ×セカンダリ上で全画面

FormStartPosition.CenterParent が指定されたフォームをモーダル表示した場合、
Load 時に「CenterToParent メソッド」が呼ばれているのですが、
FormWindowState.Maximized の状態では、Owner の中央座標への移動が
直ちに行われません。(最大化を解除した時に反映される)


' フォームをダブルクリックすると、子フォームをモーダル表示するサンプル
Public Class Form1
 Protected Overrides Sub OnDoubleClick(ByVal e As EventArgs)
  MyBase.OnDoubleClick(e)
  Using childForm As New Form2(True)
   childForm.ShowDialog(Me) 'これは OK (Form1 のある画面上に表示される)
  End Using
  Using childForm As New Form2(False)
   childForm.ShowDialog(Me) 'これは NG (初期起動時の画面上に表示される)
  End Using
 End Sub
End Class

Public Class Form2
 Inherits Form
 Public Sub New(b As Boolean)
  StartPosition = FormStartPosition.CenterParent
  If b Then
   CenterToParent()
   WindowState = FormWindowState.Maximized
  Else
   WindowState = FormWindowState.Maximized
   CenterToParent()
  End If
 End Sub
End Class



というのも、そもそも最大化されている最中に Location プロパティを操作しても、
ウィンドウ位置が変化しないものらしいです。


' フォームをクリックするたびに、プライマリモニタとセカンダリモニタを行き来するサンプル
' 最大化している時と最大化していない時では、振る舞いが異なる。
Public Class Form1
 Protected Overrides Sub OnClick(ByVal e As EventArgs)
  MyBase.OnClick(e)
  Dim AllScreens As Screen() = Screen.AllScreens
  If AllScreens.Length > 1 Then
   Location = If(Screen.FromControl(Me).DeviceName = AllScreens(1).DeviceName, AllScreens(0), AllScreens(1)).WorkingArea.Location
  Else
   MsgBox("マルチモニタ環境ではありません")
  End If
 End Sub
End Class
引用返信 編集キー/
■90003 / inTopicNo.6)  Re[3]: マルチディスプレイでの子フォームの表示位置について
□投稿者/ 粗品 (3回)-(2019/01/29(Tue) 13:03:29)
No89996 (魔界の仮面弁士 さん) に返信

ありがとうございます
おかげさまで解決しました!

>
> FormStartPosition.CenterParent が指定されたフォームをモーダル表示した場合、
> Load 時に「CenterToParent メソッド」が呼ばれているのですが、
> FormWindowState.Maximized の状態では、Owner の中央座標への移動が
> 直ちに行われません。(最大化を解除した時に反映される)
>

なるほど、
確かに最初から最大化を指定していた場合、表示後に最大化を解除したら親の中央ではなく(0,0)に表示されるとは思っていたのですが、
こういうことだったのですね


解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ