拖拉 (Drag & Drop)

專案下載:DragDrop.zip

解說

在 Windows Form 當中實作 Drag&Drop 動作的方法,其程式非常的奇特,相當難以理解。

我們必須在 MouseDown(), MouseMove(), MouseUp() 當中實作下列片段

        // 請注意,以下的 MouseEventArgs e 參數傳回的都是相對於被點選元件 richTextBox 的座標
        private void richTextBox_MouseDown(object sender, MouseEventArgs e)
        {
            px = e.X; // 記住滑鼠點下時相對於元件的 (x,y) 坐標。
            py = e.Y;
            isDragging = true;
        }
        private void richTextBox_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDragging)
            {
                // (e.X-px, e.Y-py) 儲存了滑鼠目前相對於點下時 的移動差距 (dx, dy)
                // 範例:
                // 如果差距為 (3,2),則我們應該將元件向右下移動 (3,2) 的距離
                // 以便讓滑鼠相對於元件的位置永遠不變。
                richTextBox.Left += (e.X - px); 
                richTextBox.Top += (e.Y - py);
                labelMsg.Text = "e:("+e.X+","+e.Y+") p:("+px+","+py+") "
                     + "r=("+richTextBox.Left+","+richTextBox.Top+")";
                Console.WriteLine(labelMsg.Text);
            }
        }
        private void richTextBox_MouseUp(object sender, MouseEventArgs e)
        {
            isDragging = false;
        }
	

必須注意的是 MouseEventArgs e 參數傳回的都是相對於被點選元件 richTextBox 的座標,整個程式的關鍵設計想法,是讓 MouseMove 的滑鼠點 (e.X, e.Y) 相對於元件的座標永遠保持不變,因此您會在本程式的輸出看到下列情況:

e:(54,40) p:(53,41) r=(44,11)
e:(53,41) p:(53,41) r=(44,11)
e:(53,40) p:(53,41) r=(44,10)
e:(53,41) p:(53,41) r=(44,10)
e:(54,41) p:(53,41) r=(45,10)
e:(53,41) p:(53,41) r=(45,10)
e:(54,40) p:(53,41) r=(46,9)
...
e:(54,41) p:(53,41) r=(72,23)
e:(53,41) p:(53,41) r=(72,23)
e:(53,40) p:(53,41) r=(72,22)
e:(53,41) p:(53,41) r=(72,22)
	

於是在整個過程當中,e 幾乎永遠都保持在 (53,41) 不動,但是 richTextBox 的座標確不斷的移動,因為 richTextBox 隨時都在調整位置,以便讓元件相對於滑鼠點保持固定的距離 「也就是範例輸出中的 (53,41)」。

完整程式碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace eSlide
{
    public partial class Form1 : Form
    {
        int px, py;
        bool isDragging = false;
        public Form1()
        {
            InitializeComponent();
        }
        // 請注意,以下的 MouseEventArgs e 參數傳回的都是相對於被點選元件 richTextBox 的座標
        private void richTextBox_MouseDown(object sender, MouseEventArgs e)
        {
            px = e.X; // 記住滑鼠點下時相對於元件的 (x,y) 坐標。
            py = e.Y;
            isDragging = true;
        }
        private void richTextBox_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDragging)
            {
                // (e.X-px, e.Y-py) 儲存了滑鼠目前相對於點下時 的移動差距 (dx, dy)
                // 範例:
                // 如果差距為 (3,2),則我們應該將元件向右下移動 (3,2) 的距離
                // 以便讓滑鼠相對於元件的位置永遠不變。
                richTextBox.Left += (e.X - px); 
                richTextBox.Top += (e.Y - py);
                labelMsg.Text = "e:("+e.X+","+e.Y+") p:("+px+","+py+") "
                     + "r=("+richTextBox.Left+","+richTextBox.Top+")";
                Console.WriteLine(labelMsg.Text);
            }
        }
        private void richTextBox_MouseUp(object sender, MouseEventArgs e)
        {
            isDragging = false;
        }
    }
}
	

輸出結果

e:(54,40) p:(53,41) r=(44,11)
e:(53,41) p:(53,41) r=(44,11)
e:(53,40) p:(53,41) r=(44,10)
e:(53,41) p:(53,41) r=(44,10)
e:(54,41) p:(53,41) r=(45,10)
e:(53,41) p:(53,41) r=(45,10)
e:(54,40) p:(53,41) r=(46,9)
e:(53,41) p:(53,41) r=(46,9)
e:(54,41) p:(53,41) r=(47,9)
e:(53,41) p:(53,41) r=(47,9)
e:(53,40) p:(53,41) r=(47,8)
e:(53,41) p:(53,41) r=(47,8)
e:(54,41) p:(53,41) r=(48,8)
e:(53,41) p:(53,41) r=(48,8)
e:(55,40) p:(53,41) r=(50,7)
e:(53,41) p:(53,41) r=(50,7)
e:(55,41) p:(53,41) r=(52,7)
e:(53,41) p:(53,41) r=(52,7)
e:(54,41) p:(53,41) r=(53,7)
e:(53,41) p:(53,41) r=(53,7)
e:(55,41) p:(53,41) r=(55,7)
e:(53,41) p:(53,41) r=(55,7)
e:(54,41) p:(53,41) r=(56,7)
e:(53,41) p:(53,41) r=(56,7)
e:(54,41) p:(53,41) r=(57,7)
e:(53,41) p:(53,41) r=(57,7)
e:(54,41) p:(53,41) r=(58,7)
e:(53,41) p:(53,41) r=(58,7)
e:(54,42) p:(53,41) r=(59,8)
e:(53,41) p:(53,41) r=(59,8)
e:(54,42) p:(53,41) r=(60,9)
e:(53,41) p:(53,41) r=(60,9)
e:(54,42) p:(53,41) r=(61,10)
e:(53,41) p:(53,41) r=(61,10)
e:(54,43) p:(53,41) r=(62,12)
e:(53,41) p:(53,41) r=(62,12)
e:(54,43) p:(53,41) r=(63,14)
e:(53,41) p:(53,41) r=(63,14)
e:(55,42) p:(53,41) r=(65,15)
e:(53,41) p:(53,41) r=(65,15)
e:(53,42) p:(53,41) r=(65,16)
e:(53,41) p:(53,41) r=(65,16)
e:(54,42) p:(53,41) r=(66,17)
e:(53,41) p:(53,41) r=(66,17)
e:(53,42) p:(53,41) r=(66,18)
e:(53,41) p:(53,41) r=(66,18)
e:(54,42) p:(53,41) r=(67,19)
e:(53,41) p:(53,41) r=(67,19)
e:(55,42) p:(53,41) r=(69,20)
e:(53,41) p:(53,41) r=(69,20)
e:(53,42) p:(53,41) r=(69,21)
e:(53,41) p:(53,41) r=(69,21)
e:(55,42) p:(53,41) r=(71,22)
e:(53,41) p:(53,41) r=(71,22)
e:(53,42) p:(53,41) r=(71,23)
e:(53,41) p:(53,41) r=(71,23)
e:(54,41) p:(53,41) r=(72,23)
e:(53,41) p:(53,41) r=(72,23)
e:(53,40) p:(53,41) r=(72,22)
e:(53,41) p:(53,41) r=(72,22)
	

參考文獻

  1. java2s:C# / C Sharp » GUI Windows Form » Drag Drop
  2. Drag & Drop in Mono Winforms
  3. 井民全觀點 (Jing's Perspective) Drag and drop the PictureBox

陳鍾誠 (2011年12月19日),(網頁標題) C# 視窗程式 — 拖拉 (Drag & Drop),(網站標題) 免費電子書:C# 程式設計,2011年12月19日,取自 http://cs0.wikidot.com/dragdrop ,網頁修改第 5 版。

arrow
arrow

    Johnson峰 發表在 痞客邦 留言(0) 人氣()