LoginSignup
4
6

More than 3 years have passed since last update.

【C# Form】マルチモニタ環境での座標の扱い

Last updated at Posted at 2021-05-05

ちょうどまとまっている資料が見つからなかったので、まとめてみました。

環境

C# - Winodws Form Application (Visual Studio 2017 , .NET Framework 4.5)

マルチモニタ環境での座標の扱い

表示領域と移動について

自作のフォームアプリをマルチモニタ対応するために色々弄ってみました。
こういうマルチモニタ環境があるとします。
disp01.png
小さいディスプレイをサブモニタとして使用している私の環境です。
この状態では、表示領域はこうなってます。
disp02.png
プライマリディスプレイの左上が(0,0)であり、セカンダリディスプレイはその左側にあるのでX座標はマイナスになります。
つまり、フォームのLeft,Topプロパティに雑に座標を指定すれば自動的にその位置に応じたディスプレイ上に表示させることができます。
結論として、フォームの移動や配置についてのケアは殆ど要らないと言えるでしょう。

逆に言うと、「座標がマイナスならディスプレイからはみ出ている」というロジックの方を改めなければなりません。

ディスプレイ領域の取得

Formはどこのディスプレイ上にあるの?

System.Windows.Forms.Screen.FromControlメソッドにフォームを引数で渡せばScreenオブジェクトを取ることができます。
あとはBoundsでディスプレイ領域の矩形が、WorkingAreaでタスクバーを除いた領域が取れます。

System.Drawing.Rectangle rect = System.Windows.Forms.Screen.FromControl(this).Bounds;

結果(矩形)だけが欲しいのなら、Screen.GetBoundsでも良いようです。

System.Drawing.Rectangle rect = System.Windows.Forms.Screen.GetBounds(this);

2つのモニタを跨った場合は、最大部分を保持するディスプレイの方が返されます。中央の座標を含む方ですね。

マウスがあるディスプレイは?

今の“アクティブ”なディスプレイは、マウスのある位置ではないかと思います。マウスのあるディスプレイにフォームを移動させたいこともあるでしょう。
ScreenFromPointがあります。

System.Drawing.Rectangle rect = System.Windows.Forms.Screen.FromPoint(Cursor.Position).Bounds;

また、GetBoundsの引数にpoint型も渡せます。

System.Drawing.Rectangle rect = System.Windows.Forms.Screen.GetBounds(Cursor.Position);

ディスプレイの中に表示されているかどうかのチェック

基本的にはScreen.FromControlで行けると思いますが、ディスプレイの方から探す方法も抑えておくと良いかも。

public static bool IsOnScreen(System.Windows.Forms.Form frm)
{
    foreach (System.Windows.Forms.Screen s in System.Windows.Forms.Screen.AllScreens)
    {
        if (s.WorkingArea.Contains(new System.Drawing.Rectangle(frm.Location, frm.Size)))
        {
            return true;
        }
    }
    return false;
}

これははみ出てない事に対するチェック。ちなみにこれ、モニタ2つを跨っている場合ははみ出てる判定になります。

ディスプレイの中にフォームを収めるには

あとはまぁ、適当にやればよろしいかと。

    if (this.WindowState == System.Windows.Forms.FormWindowState.Normal)
    {
        var rect = System.Windows.Forms.Screen.GetBounds(this);
        this.Left = (rect.Left + rect.Width > this.Left + this.Width) ? this.Left : rect.Left + rect.Width - this.Width;
        this.Left = (rect.Left < this.Left) ? this.Left : rect.Left;
        this.Top = (rect.Top + rect.Height > this.Top + this.Height) ? this.Top : rect.Top + rect.Height - this.Height;
        this.Top = (rect.Top < this.Top) ? this.Top : rect.Top;
    }

これを入れておけば、「モニタ外してからアプリを起動したら行方不明に!」という事態は避けられると思います。


独学のため正確でない可能性があります。
(っ・x・)っ きゅ

参考

4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6