在 Windows Forms 應用程式中,若需讓使用者在**執行階段**以滑鼠自由拖曳移動控制項(如 Button、Panel、Label),可封裝一個 `DragControl` 類別,處理 `MouseDown`、`MouseMove` 事件並計算位移。本文提供完整可復用的實作碼。
using System;
using System.Windows.Forms;
namespace WinFormsApp_DragControls
{
public class DragControl
{
private readonly Control _control;
private int _mouseX, _mouseY; // 滑鼠按下時相對控制項左上角的座標
public DragControl(Control control)
{
_control = control ?? throw new ArgumentNullException(nameof(control));
_control.MouseDown += Control_MouseDown;
_control.MouseMove += Control_MouseMove;
}
private void Control_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
// 記錄滑鼠在控制項內的相對位置
_mouseX = e.X;
_mouseY = e.Y;
}
}
private void Control_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
// 計算新位置:控制項目前位置 + (目前滑鼠位置 - 按下時相對位置)
int newLeft = _control.Left + (e.X - _mouseX);
int newTop = _control.Top + (e.Y - _mouseY);
// 可選:限制不超出父容器邊界
// var parent = _control.Parent;
// if (parent != null) {
// newLeft = Math.Max(0, Math.Min(newLeft, parent.ClientSize.Width - _control.Width));
// newTop = Math.Max(0, Math.Min(newTop, parent.ClientSize.Height - _control.Height));
// }
_control.Left = newLeft;
_control.Top = newTop;
}
}
}
}
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
// 讓 button1、panel1、label1 在執行時可拖曳
new DragControl(button1);
new DragControl(panel1);
new DragControl(label1);
}
}
| 步驟 | 說明 |
|---|---|
| MouseDown | 記錄滑鼠相對控制項左上角的座標 (`e.X`, `e.Y`),作為位移基準。 |
| MouseMove (左鍵按住) | 新位置 = 原位置 + (目前滑鼠座標 - 按下時相對座標)。直接修改 `Control.Left`/`Top` 即可移動。 |
| 只處理左鍵 | 避免右鍵、中鍵誤觸發移動。 |
透過封裝 `MouseDown`/`MouseMove` 事件與簡單座標運算,`DragControl` 類別能以 **10 行核心程式碼** 賦予任意 `Control` 執行階段拖曳移動能力。這是 WinForms 打造可視化設計器、儀表板編輯器、自訂版面配置工具的基礎組件。