1. 设置无边框模式

选中要去除边框的窗体,按F4调出其属性面板,在属性面板中找到 FormBorderStyle ,并选择 ​None,即可将窗体设置成无边框模式;默认是无法随意拖动的,也没有最大化最小化关闭按钮。

2. 通过Panel控件实现窗体移动

实现方法 :在窗体的头部添加 Panel 控件,通过 Panel 的 MouseDown、MouseMove 事件实现窗体移动;(这里的话可以添加一个背景色更好)

实现原理: 直接通过修改窗体位置从而达到移动窗体的效果;

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//定义一个位置信息Point用于存储鼠标位置
private Point mpoint;
/// <summary>
/// 鼠标移动事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.Location = new Point(this.Location.X + e.X - mpoint.X, this.Location.Y + e.Y - mpoint.Y);
}
}
/// <summary>
/// 鼠标按下事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
mpoint = new Point(e.X, e.Y);
}

3. 通过窗体事件实现窗体移动

实现方法:通过窗体MouseDown、MouseMove、MouseUp事件实现窗体移动;

代码演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//定义一个位置信息Point用于存储鼠标位置
private Point mpoint;
// 定义一个bool变量用于判断鼠标是否按下
private bool isMouseDown = false;

/// <summary>
/// 鼠标释放事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
// 鼠标左键按下
mpoint = e.Location;
// 记录鼠标按下状态
if (e.Button == MouseButtons.Left)
{
isMouseDown = true;
}
}
/// <summary>
/// 鼠标移动事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left && isMouseDown)
{

Location += new Size(e.Location.X - mpoint.X, e.Location.Y - mpoint.Y);
}
}
/// <summary>
/// 鼠标释放事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
isMouseDown = false; // 鼠标左键释放
}

3.1. 🧱 前提准备

1
2
private Point mpoint;          // 用来记住“鼠标刚按下去时,在窗体内的位置”
private bool isMouseDown = false; // 标记“鼠标是不是正按着”

比如你点在窗体标题栏(或任意位置)的 (50, 30) 处,mpoint 就记下这个点。


3.2. 1️⃣ 鼠标按下时(MouseDown

1
2
3
4
5
6
7
8
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
mpoint = e.Location; // 记录:鼠标在窗体内的坐标(比如 (50,30))
if (e.Button == MouseButtons.Left)
{
isMouseDown = true; // 标记:现在鼠标左键按下了
}
}

✅ ​作用

  • 记住你“从哪里开始拖”
  • 告诉程序:“我要开始拖窗体了!”

3.3. 2️⃣ 鼠标移动时(MouseMove

1
2
3
4
5
6
7
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && isMouseDown)
{
Location += new Size(e.Location.X - mpoint.X, e.Location.Y - mpoint.Y);
}
}

🔍 ​关键逻辑拆解

  • e.Location​:当前鼠标在窗体内部的坐标(比如现在移到了 (60, 40))
  • mpoint:最初按下的位置(比如 (50, 30))
  • e.Location - mpoint​ = (10, 10) → 表示鼠标相对于按下点,移动了多少

👉 于是:

1
Location += new Size(10, 10);

就是把​整个窗体的位置向右下移动 10 像素

🔁 每次鼠标一动,就计算“偏移量”,然后让窗体跟着偏移 —— ​看起来就像你拖着窗体走

💡 为什么用 Location += ...​?
因为 Location 是窗体左上角在屏幕上的坐标。加一个偏移量,窗体就跟着动。


3.4. 3️⃣ 鼠标松开时(MouseUp

1
2
3
4
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
isMouseDown = false; // 标记:鼠标松开了,停止拖拽
}

✅ ​作用

  • 告诉程序:“我不拖了!”
  • 下次再移动鼠标,MouseMove​ 里的 if 条件不成立,窗体就不会乱跑了

3.5. 🎯 整体流程(举个栗子🌰)

  1. 你在窗体上 (50, 30) 处按下鼠标左键
    mpoint = (50, 30)​,isMouseDown = true
  2. 你把鼠标拖到 (80, 60)
    e.Location = (80, 60)
    → 偏移量 = (80-50, 60-30) = (30, 30)
    Location += (30, 30) → 窗体整体右移 30、下移 30
  3. 你松开鼠标
    isMouseDown = false
    → 再移动鼠标,窗体不动了

3.6. ⚠️ 注意事项

  • 这段代码通常用在 ​无边框窗体​(FormBorderStyle = None)上,因为默认窗体可以拖标题栏移动,不需要自己实现。
  • 如果窗体有标题栏,这样写会导致“点哪都能拖”,可能不符合用户习惯。
  • Location​ 改变的是窗体在​屏幕上的绝对位置,不是相对位置。

3.7. ✅ 总结一句话:

这段代码实现了 “鼠标按住窗体任意位置拖动,窗体跟着走” 的功能,核心是:
记录起点 → 计算偏移 → 移动窗体 → 松手停止