2011年03月20日

フォームの端をドラッグしてサイズ変更する機能を提供するクラス(C#用)

C#のフォームは標準でフォームの端をドラッグしてサイズ変更が可能ですが、フォームのスタイルをサイズ変更が出来ないスタイルに変更したとしても、このクラスを使ってサイズ変更させることが可能です。
具体的には、FormBorderStyleをNoneにしたフォームでも、枠をドラッグすることでサイズ変更が可能になります。
色々ツッコミ所はあるかもしれませんが、ご容赦を。(たぶん、もっとスマートに書けるはずです)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

namespace Com.Mirano.Forms
{
    /// <summary>
    /// フォームの端をドラッグしてサイズ変更するクラス
    /// </summary>
    class FormDragResizer
    {
        // サイズ変更の対象となるフォーム
        Form resizeForm;

        /// <summary>
        /// サイズ変更の対象となる枠の位置
        /// </summary>
        public enum ResizeDirection
        {
            None = 0,
            Top = 1,
            Left = 2,
            Bottom = 4,
            Right = 8,
            All = 15
        }

        // サイズ変更が有効になる枠
        ResizeDirection resizeDirection;

        // サイズ変更中を表す状態
        ResizeDirection resizeStatus;

        // サイズ変更が有効になる範囲の幅
        int resizeAreaWidth;

        // 標準のカーソル
        Cursor defaultCursor;

        // マウスをクリックした位置
        Point lastMouseDownPoint;

        // マウスをクリックした時点のサイズ
        Size lastMouseDownSize;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="resizeForm">サイズ変更の対象となるフォーム</param>
        /// <param name="resizeDirection">サイズ変更が有効になる枠</param>
        /// <param name="resizeAreaWidth">サイズ変更が有効になる範囲の幅</param>
        public FormDragResizer(Form resizeForm, ResizeDirection resizeDirection, int resizeAreaWidth)
        {
            this.resizeForm = resizeForm;
            this.resizeDirection = resizeDirection;
            this.resizeAreaWidth = resizeAreaWidth;

            // 現時点でのカーソルを保存しておく
            defaultCursor = resizeForm.Cursor;

            // イベントハンドラを追加
            resizeForm.MouseDown += new MouseEventHandler(resizeForm_MouseDown);
            resizeForm.MouseMove += new MouseEventHandler(resizeForm_MouseMove);
            resizeForm.MouseUp += new MouseEventHandler(resizeForm_MouseUp);
        }

        /// <summary>
        /// マウスボタン押下イベントハンドラ
        /// </summary>
        void resizeForm_MouseDown(object sender, MouseEventArgs e)
        {
            // クリックしたポイントを保存する
            lastMouseDownPoint = e.Location;

            // クリックした時点でのフォームのサイズを保存する
            lastMouseDownSize = resizeForm.Size;

            // クリックした位置から、サイズ変更する方向を決める
            resizeStatus = ResizeDirection.None;

            // 上の判定
            if ((resizeDirection & ResizeDirection.Top) == ResizeDirection.Top)
            {
                Rectangle topRect = new Rectangle(0, 0, resizeForm.Width, resizeAreaWidth);
                if (topRect.Contains(e.Location))
                {
                    resizeStatus |= ResizeDirection.Top;
                }
            }

            // 左の判定
            if ((resizeDirection & ResizeDirection.Left) == ResizeDirection.Left)
            {
                Rectangle leftRect = new Rectangle(0, 0, resizeAreaWidth, resizeForm.Height);
                if (leftRect.Contains(e.Location))
                {
                    resizeStatus |= ResizeDirection.Left;
                }
            }

            // 下の判定
            if ((resizeDirection & ResizeDirection.Bottom) == ResizeDirection.Bottom)
            {
                Rectangle bottomRect = new Rectangle(0, resizeForm.Height - resizeAreaWidth, resizeForm.Width, resizeAreaWidth);
                if (bottomRect.Contains(e.Location))
                {
                    resizeStatus |= ResizeDirection.Bottom;
                }
            }

            // 右の判定
            if ((resizeDirection & ResizeDirection.Right) == ResizeDirection.Right)
            {
                Rectangle rightRect = new Rectangle(resizeForm.Width - resizeAreaWidth, 0, resizeAreaWidth, resizeForm.Height);
                if (rightRect.Contains(e.Location))
                {
                    resizeStatus |= ResizeDirection.Right;
                }
            }

            // サイズ変更の対象だったら、マウスキャプチャー
            if (resizeStatus != ResizeDirection.None)
            {
                resizeForm.Capture = true;
            }
        }

        /// <summary>
        /// マウス移動イベントハンドラ
        /// </summary>
        void resizeForm_MouseMove(object sender, MouseEventArgs e)
        {
            // サイズ変更が有効になる枠の上にカーソルが乗ったら
            // マウスカーソルをサイズ変更用のものに変更する

            // どの枠の上にカーソルが乗っているか
            ResizeDirection cursorPos = ResizeDirection.None;

            // 上の判定
            if ((resizeDirection & ResizeDirection.Top) == ResizeDirection.Top)
            {
                Rectangle topRect = new Rectangle(0, 0, resizeForm.Width, resizeAreaWidth);
                if (topRect.Contains(e.Location))
                {
                    cursorPos |= ResizeDirection.Top;
                }
            }

            // 左の判定
            if ((resizeDirection & ResizeDirection.Left) == ResizeDirection.Left)
            {
                Rectangle leftRect = new Rectangle(0, 0, resizeAreaWidth, resizeForm.Height);
                if (leftRect.Contains(e.Location))
                {
                    cursorPos |= ResizeDirection.Left;
                }
            }

            // 下の判定
            if ((resizeDirection & ResizeDirection.Bottom) == ResizeDirection.Bottom)
            {
                Rectangle bottomRect = new Rectangle(0, resizeForm.Height - resizeAreaWidth, resizeForm.Width, resizeAreaWidth);
                if (bottomRect.Contains(e.Location))
                {
                    cursorPos |= ResizeDirection.Bottom;
                }
            }

            // 右の判定
            if ((resizeDirection & ResizeDirection.Right) == ResizeDirection.Right)
            {
                Rectangle rightRect = new Rectangle(resizeForm.Width - resizeAreaWidth, 0, resizeAreaWidth, resizeForm.Height);
                if (rightRect.Contains(e.Location))
                {
                    cursorPos |= ResizeDirection.Right;
                }
            }

            // カーソルを変更

            // 左上(左上から右下への斜め矢印)
            if (((cursorPos & ResizeDirection.Left) == ResizeDirection.Left)
                && ((cursorPos & ResizeDirection.Top) == ResizeDirection.Top))
            {
                resizeForm.Cursor = Cursors.SizeNWSE;
            }
            // 右下(左上から右下への斜め矢印)
            else if (((cursorPos & ResizeDirection.Right) == ResizeDirection.Right)
                && ((cursorPos & ResizeDirection.Bottom) == ResizeDirection.Bottom))
            {
                resizeForm.Cursor = Cursors.SizeNWSE;
            }
            // 右上(右上から左下への斜め矢印)
            else if (((cursorPos & ResizeDirection.Right) == ResizeDirection.Right)
                && ((cursorPos & ResizeDirection.Top) == ResizeDirection.Top))
            {
                resizeForm.Cursor = Cursors.SizeNESW;
            }
            // 左下(右上から左下への斜め矢印)
            else if (((cursorPos & ResizeDirection.Left) == ResizeDirection.Left)
                && ((cursorPos & ResizeDirection.Bottom) == ResizeDirection.Bottom))
            {
                resizeForm.Cursor = Cursors.SizeNESW;
            }
            // 上(上下矢印)
            else if ((cursorPos & ResizeDirection.Top) == ResizeDirection.Top)
            {
                resizeForm.Cursor = Cursors.SizeNS;
            }
            // 左(左右矢印)
            else if ((cursorPos & ResizeDirection.Left) == ResizeDirection.Left)
            {
                resizeForm.Cursor = Cursors.SizeWE;
            }
            // 下(上下矢印)
            else if ((cursorPos & ResizeDirection.Bottom) == ResizeDirection.Bottom)
            {
                resizeForm.Cursor = Cursors.SizeNS;
            }
            // 右(左右矢印)
            else if ((cursorPos & ResizeDirection.Right) == ResizeDirection.Right)
            {
                resizeForm.Cursor = Cursors.SizeWE;
            }
            // どこにも属していない(デフォルト)
            else
            {
                resizeForm.Cursor = defaultCursor;
            }

            // ボタンを押していた場合は、サイズ変更を行う
            if (e.Button == MouseButtons.Left)
            {
                // ドラッグにより移動した距離を計算
                int diffX = e.X - lastMouseDownPoint.X;
                int diffY = e.Y - lastMouseDownPoint.Y;

                // 上
                if ((resizeStatus & ResizeDirection.Top) == ResizeDirection.Top)
                {
                    // まず、ドラッグした距離分だけサイズを変更する
                    // その後、フォームの位置を調整する
                    // (順番を逆にすると、ちょっとちらつく?)
                    int h = resizeForm.Height;
                    resizeForm.Height -= diffY;
                    resizeForm.Top += h - resizeForm.Height;
                }
                // 左
                if ((resizeStatus & ResizeDirection.Left) == ResizeDirection.Left)
                {
                    // 上と同じ
                    int w = resizeForm.Width;
                    resizeForm.Width -= diffX;
                    resizeForm.Left += w - resizeForm.Width;
                }
                // 下
                if ((resizeStatus & ResizeDirection.Bottom) == ResizeDirection.Bottom)
                {
                    // マウスクリックした時点のサイズを基点として、
                    // ドラッグした距離分だけサイズを変更する
                    resizeForm.Height = lastMouseDownSize.Height + diffY;
                }
                // 右
                if ((resizeStatus & ResizeDirection.Right) == ResizeDirection.Right)
                {
                    // マウスクリックした時点のサイズを基点として、
                    // ドラッグした距離分だけサイズを変更する
                    resizeForm.Width = lastMouseDownSize.Width + diffX;
                }
            }
        }

        /// <summary>
        /// マウスボタン押上イベントハンドラ
        /// </summary>
        void resizeForm_MouseUp(object sender, MouseEventArgs e)
        {
            // マウスキャプチャーを終了する
            resizeForm.Capture = false;
        }
    }
}

使い方

// 変数を定義しておき
FormDragResizer formResizer;

private void InitializeForm()
{
    // Formのイニシャル処理で生成する
    formResizer = new FormDragResizer(this, FormDragResizer.ResizeDirection.All, 8);
}

第2引数は、サイズ変更を許す位置を指定します。
第3引数は、ドラッグを有効にする範囲を、フォームの端からの距離で指定します。
例では、フォームの端から8ドット分がドラッグが有効な範囲になります。
フォームをドラッグして移動させる機能を提供するクラス(C#用)と一緒に使う場合は、下記のようにします。

// 両方の変数を定義しておき
FormDragResizer formResizer;
FormDragMover formMover;

private void InitializeForm()
{
    // Formのイニシャル処理で生成する
    formResizer = new FormDragResizer(this, FormDragResizer.ResizeDirection.All, 8);
    formMover = new FormDragMover(this, 8);
}

FormDragResizerとFormDragMoverのマージンは同じ値にするか、FormDragMoverのマージンの方を大きくする必要があります。

良かったらクリックしてください
にほんブログ村 IT技術ブログ プログラム・プログラマーへ  人気ブログランキングへ

posted by among at 11:03 | Comment(0) | TrackBack(0) | C#

2011年03月06日

フォームをドラッグして移動させる機能を提供するクラス(C#用)

以前に『フォームをドラッグして移動させる方法』という記事を書きましたが、この機能をクラス化したので公開します。
色々ツッコミ所はあるかもしれませんが、ご容赦を。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

namespace Com.Mirano.Forms
{
    /// <summary>
    /// フォームをドラッグして移動するクラス
    /// </summary>
    class FormDragMover
    {
        // 移動の対象となるフォーム
        Form moveForm;

        // 移動中を表す状態
        bool moveStatus;

        // ドラッグを無効とする幅(フォームの端をサイズ変更に使うときなど)
        int noDragAreaWidth;

        // 標準のカーソル
        Cursor defaultCursor;

        // マウスをクリックした位置
        Point lastMouseDownPoint;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="moveForm">移動の対象となるフォーム</param>
        /// <param name="noDragAreaWidth">ドラッグを無効とする幅</param>
        public FormDragMover(Form moveForm, int noDragAreaWidth)
        {
            this.moveForm = moveForm;
            this.noDragAreaWidth = noDragAreaWidth;

            // 現時点でのカーソルを保存しておく
            defaultCursor = moveForm.Cursor;

            // イベントハンドラを追加
            moveForm.MouseDown += new MouseEventHandler(moveForm_MouseDown);
            moveForm.MouseMove += new MouseEventHandler(moveForm_MouseMove);
            moveForm.MouseUp += new MouseEventHandler(moveForm_MouseUp);
        }

        /// <summary>
        /// マウスボタン押下イベントハンドラ
        /// </summary>
        void moveForm_MouseDown(object sender, MouseEventArgs e)
        {
            // 左クリック時のみ処理する。左クリックでなければ何もしない
            if ((e.Button & MouseButtons.Left) != MouseButtons.Left) return;

            // 移動が有効になる範囲
            // 例えばフォームの端から何ドットかをサイズ変更用の領域として使用する場合、
            // そこを避けるために使う。
            Rectangle moveArea = new Rectangle(
                noDragAreaWidth, noDragAreaWidth, 
                moveForm.Width - (noDragAreaWidth * 2), moveForm.Height - (noDragAreaWidth * 2));

            // クリックした位置が移動が有効になる範囲であれば、移動中にする
            if (moveArea.Contains(e.Location))
            {
                // 移動中にする
                moveStatus = true;

                // クリックしたポイントを保存する
                lastMouseDownPoint = e.Location;

                // マウスキャプチャー
                moveForm.Capture = true;
            }
            else
            {
                moveStatus = false;
            }
        }

        /// <summary>
        /// マウス移動イベントハンドラ
        /// </summary>
        void moveForm_MouseMove(object sender, MouseEventArgs e)
        {
            // 移動中の場合のみ処理。移動中でなければ何もせず終わる
            if (moveStatus == false) return;

            // 左ボタン押下中のみ処理する。押下中ではないときは何もしない。
            if ((e.Button & MouseButtons.Left) != MouseButtons.Left) return;

            // マウスカーソルの変更
            moveForm.Cursor = Cursors.SizeAll;

            // フォームの移動
            //*//通常の場合
            moveForm.Left += e.X - lastMouseDownPoint.X;
            moveForm.Top += e.Y - lastMouseDownPoint.Y;
            //*/

            // 吸着の処理は後回し
        }

        /// <summary>
        /// マウスボタン押上イベントハンドラ
        /// </summary>
        void moveForm_MouseUp(object sender, MouseEventArgs e)
        {
            // 左ボタンのみ処理する。左ボタンではないときは何もしない。
            if ((e.Button & MouseButtons.Left) != MouseButtons.Left) return;

            // 移動を終了する
            moveStatus = false;

            // マウスキャプチャーを終了する
            moveForm.Capture = false;

            // マウスカーソルを戻す
            moveForm.Cursor = defaultCursor;
        }
    }
}

使い方

// 変数を定義しておき
FormDragMover formMover;

private void InitializeForm()
{
    // Formのイニシャル処理で生成する
    formMover = new FormDragMover(this, 8);
}

第2引数はドラッグを有効にする範囲を、フォームの端からの距離(マージン)で指定します。
例では、フォームの端から8ドットはドラッグしても移動しません。
これは、フォームの枠をドラッグしてサイズ変更をさせるためです。

[2011-04-08追記]
moveForm_MouseUpにマウスカーソルを戻す処理を追加しました。

良かったらクリックしてください
にほんブログ村 IT技術ブログ プログラム・プログラマーへ  人気ブログランキングへ

posted by among at 21:49 | Comment(0) | TrackBack(0) | C#