フォームを画面の端に吸着させる方法(C#用メモ)

フォームが画面の端に近づいたときに、端に吸着(スナップ)させる方法。
基本的には力業です。
フォームをドラッグして移動させる方法(C#用メモ) - amongの雑記』で紹介した方法を使います。

フォームを直接動かすのではなく、フォームの移動先の領域を定義しておき、それが画面の端に吸着しそうな距離であれば、吸着させます。
吸着しそうな距離かどうかは、“フォームの移動先の領域”と“画面の端の領域”を定義して、領域が重なっているかチェックします。
今回はRectangleのIntersectsWithを使用しましたが、if文で判定しても構いません。

//マウスが動いたとき
private void Form1_MouseMove(object sender,
    System.Windows.Forms.MouseEventArgs e)
{
    if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
    {
        // 吸着するサイズ
        Size gap = new Size(16, 16);

        // 移動先のフォーム位置
        Rectangle newPosition = new Rectangle(
            this.Left + e.X - mousePoint.X,
            this.Top + e.Y - mousePoint.Y,
            this.Width,
            this.Height);
        // 判定用のRECT
        Rectangle newRect = new Rectangle();

        // 作業領域の取得(この作業領域の内側に吸着する)
        Size area = new Size(
            System.Windows.Forms.Screen.GetWorkingArea(this).Width,
            System.Windows.Forms.Screen.GetWorkingArea(this).Height);

        // 画面端の判定用(画面の端の位置に、吸着するサイズ分のRECTを定義する)
        Rectangle rectLeft = new Rectangle(
                                    0, 
                                    0, 
                                    gap.Width, 
                                    area.Height);
        Rectangle rectTop = new Rectangle(
                                    0, 
                                    0, 
                                    area.Width, 
                                    gap.Height);
        Rectangle rectRight = new Rectangle(
                                    area.Width - gap.Width, 
                                    0, 
                                    gap.Width, 
                                    area.Height);
        Rectangle rectBottom = new Rectangle(
                                    0, 
                                    area.Height - gap.Height, 
                                    area.Width, 
                                    gap.Height);
        // 衝突判定
        // 判定用のRECTを自分のウィンドウの隅に重ねるように移動し、
        // 画面端の判定用のRECTと衝突しているかチェックする。
        // 衝突していた場合は、吸着させるように移動する

        // 左端衝突判定
        {
            newRect = newPosition;
            newRect.Width = gap.Width;

            if (newRect.IntersectsWith(rectLeft))
            {
                // 左端に吸着させる
                newPosition.X = 0;
            }
        }
        // 右端衝突判定
        {
            newRect = newPosition;
            newRect.X = newPosition.Right - gap.Width;  // ウィンドウの右隅
            newRect.Width = gap.Width;

            if (newRect.IntersectsWith(rectRight))
            {
                // 右端に吸着させる
                newPosition.X = area.Width - this.Width;
            }
        }
        // 上端衝突判定
        {
            newRect = newPosition;
            newRect.Height = gap.Height;

            if (newRect.IntersectsWith(rectTop))
            {
                // 上端に吸着させる
                newPosition.Y = 0;
            }
        }
        // 下端衝突判定
        {
            newRect = newPosition;
            newRect.Y = newPosition.Bottom - gap.Height; // ウィンドウの下端
            newRect.Height = gap.Height;

            if (newRect.IntersectsWith(rectBottom))
            {
                // 下端に吸着させる
                newPosition.Y = area.Height - this.Height;
            }
        }

        // 実際に移動させる
        this.Left = newPosition.Left;
        this.Top = newPosition.Top;
    }
}