今日ちょっとソフトを書いていて迷ってしまったので、記事にしたいと思います。
背景 困った事
マルチディスプレイでアプリケーションを作成中に、メインフォームの横に新しいフォームを表示しようとした時に、新しいフォームがモニタ(スクリーン)上からはみ出てしまった。
そこで、はみ出た分をずらして表示したいと考えた。
ロケーション(フォームの座標)は、プライマリモニタ(メインディスプレイ)の左上を原点座標としての座標で表記される。
■わからない事 ①メインフォームがどのモニタに表示されているか? ②セカンダリモニタの時にどうやって表示位置を計算すればいいのか?
全モニタ(スクリーン)の情報を取得する
初めにモニタの情報を取得しましょう。
using System.Windows.Forms; foreach (Screen scr in Screen.AllScreens) { //ディスプレイのデバイス名を表示 Console.WriteLine("デバイス名:{0}", scr.DeviceName); //ディスプレイの左上の座標を表示 Console.WriteLine("X:{0} Y:{1}", scr.Bounds.X, scr.Bounds.Y); //ディスプレイの大きさを表示 Console.WriteLine("高さ:{0} 幅:{1}", scr.Bounds.Height, scr.Bounds.Width); }
全てのモニタ情報を取得して分かった事
モニタ情報を取得すれば、座標系は計算できそうですね。
メインフォームは、どのモニタに表示されているか?
はみ出ているかは、Rectangle型のプロパティContainsを使います。
Containsは、調べたい要素が含まれているか確認する為によく使用されます。
foreach (Screen scr in Screen.AllScreens)
{
if (scr.WorkingArea.Contains(fm.Location) == true)
{
//メインフォーム(左上)が表示されているモニタの時
}
}
スクリーンのワーキングエリアにメインフォームが含まれているかを確認する事ができました。
新しく表示するフォームはモニタからはみ出ているのか?
次に、表示したいフォームがはみ出ているか確認します。
上図の赤丸部の座標がモニタに含まれているか確認します。
先ほどと同様にContainsを使います。
foreach (Screen scr in Screen.AllScreens)
{
//メインフォーム(左上)が表示されているモニタの時
if (scr.WorkingArea.Contains(fm.Location) == true)
{
//表示するモニタの右上がモニタをはみ出しているか確認
if (scr.WorkingArea.Contains(fm.Location.X + fm.Size.Width + this.Size.Width, fm.Location.Y) == false)
{
//はみ出ている時
}
}
}
はみ出ているかの判断ができました。
新しく表示するフォームの表示位置を計算する。
まず初めにメインフォームの横に表示したいので、初期値としては、メインフォーム横の座標にしましょう。
int x = fm.Location.X + fm.Size.Width; //表示したいウィンドウの左の座標
int y = fm.Location.Y; //表示したいウィンドウの上の座標
次にはみ出している時の計算方法です。
はみ出した量を計算して、その分オフセットしようと思ったのですが、
やりたい事を整理すると、モニタの位置とモニタサイズから最大値をが分かるので、表示したいモニタがはみ出しているのであれば、表示したいフォームのサイズ分引けばいいと気づきました!!(おそっっwww)
int x = fm.Location.X + fm.Size.Width; //表示したいウィンドウの左の座標
int y = fm.Location.Y; //表示したいウィンドウの上の座標
foreach (Screen scr in Screen.AllScreens)
{
//メインフォーム(左上)が表示されているモニタの時
if (scr.WorkingArea.Contains(fm.Location) == true)
{
//表示するモニタの右上がモニタをはみ出しているか確認
if (scr.WorkingArea.Contains(fm.Location.X + fm.Size.Width + this.Size.Width, fm.Location.Y) == false)
{
//最大座標からフォームサイズ分引く
x = scr.Bounds.X + scr.WorkingArea.Width - this.Size.Width;
}
}
}
//指定位置にフォームを表示
this.StartPosition = FormStartPosition.Manual;
this.Location = new Point(x, y);
これでX方向のモニタからのはみ出しに対応できるようになりました。
Y方向も同じ要領でやってみましょう!!
最後に、新しいフォームのプロパティStartPositionをマニュアルに設定して、Locationを指定しましょう。
まとめ
結果的にプライマリモニタ、マルチディスプレイとか関係ありませんでしたwww
モニタ(スクリーン)情報を取得し、表示しているフォーム/表示したいフォームがどのモニタに表示されているか知りたい時はContainsを使えばわかりました。
表示したい位置も、やりたい事を違う視点で見る事で、算出式がシンプルになりました。
メモメモ。。。
業務でプログラミング(C#/VB/Python)を作っている。
挫折を何回も繰り返し、幾度の壁を乗り越えてきた。
乗り越えてきた事を忘れないように記録に残す。
同じ思いをしている人への情報提供になれたらと思う。
基本は初心者に向けたプログラムの情報を提供する。
コメント