C# 視窗程式 -- 拖拉 (Drag & Drop)

基礎篇

C# 簡介

開發環境

變數與運算

流程控制

陣列

函數

物件

例外處理

函式庫篇

檔案處理

資料結構

正規表達式

Thread

應用篇

視窗程式

媒體影音

網路程式

遊戲程式

手機程式

資料庫

雲端運算

特殊功能

委派

擴展方法

序列化

LinQ

WPF

網路資源

教學影片

投影片

教學文章

軟體下載

考題解答

101習題

專案下載: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
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License