ユーザーコントロールをドラッグアンドドロップで移動

最近C#も触っております。
C#で、UMLペイントツールのようなものを作ろうと思うと、ユーザーによる描画オブジェクトの移動が行えなければ話になりません。クラス図であればクラスの四角い箱です。とりあえず、そのやり方がわかったので、メモ。

独自定義のユーザーコントロール作成

とりあえずクラス図の「クラス」をイメージしてユーザーコントロールを作成します。
[追加]-[ユーザーコントロール]を選択し、「ClassPicture」とでも名前をつけます。

一番肝となるイベントは、「MouseMove」です。コントロール上でマウスが移動すると呼ばれます。とはいえ、コントロール上をマウスが移動しただけでイベントが走っても困ります。あくまでドラッグアンドドロップした時のみユーザーコントロールオブジェクトを移動したいわけですから、「MouseDown」「MouseUp」イベントを使って、ドラッグアンドドロップという状態かどうかを判定するコードを書きます。

        private void ClassPicuture_MouseDown(object sender, MouseEventArgs e)
        {
            isDraggable = true;
        }

        private void ClassPicuture_MouseUp(object sender, MouseEventArgs e)
        {
            isDraggable = false;
        }

isDraggableはClassPicutureのメンバ変数として新たに定義しておきます。
こうしておけば、MouseMoveの冒頭に以下のように書くだけで、ドラッグアンドドロップ時意外は何も処理が行われなくなります。

        private void ClassPicture_MouseMove(object sender, MouseEventArgs e)
        {
            if ( !isDraggable )
            {
                return;
            }

            // 移動処理
        }

後は、移動処理だけです。
最初にMouseDownした時点を始点として、後は移動分を差分で設定すればいいだけ。完成したコードは以下。
pointはSystem.Drawing.Point型でこれまたメンバ変数として定義しておきます。

        private void ClassPicutre_MouseDown(object sender, MouseEventArgs e)
        {
            isDraggable = true;
            point.X = e.X;
            point.Y = e.Y;
        }

        private void ClassPicutre_MouseMove(object sender, MouseEventArgs e)
        {
            if ( !isDraggable )
            {
                return;
            }

            //移動処理
            this.Left += e.X - point.X;
            this.Top += e.Y - point.Y;
        }

        private void ClassPicutre_MouseUp(object sender, MouseEventArgs e)
        {
            isDraggable = false;
        }

あとはこの独自コントロールをForm上に配置するなどすれば使えます。

他にやりたいこととしては、コントロールの端っこを引っ張るとサイズが変わるといったこと。ちょっと調べた限りでは簡単には出来なさそう。何で最初っから用意してくれてないんだー。