1、原理
/*
* 理解了下面的几个概念,就能完全明白相对坐标的变化.
* MouseEventArgs e 为事件鼠标参数,因此,e.Location 指示了位于事件源上的光标坐标
* Cursor.Position 获取的是相对于用户屏幕的光标坐标
* PointToClient() 方法可将屏幕坐标 Cursor.Position 换算成工作区的坐标
* 因此,换算后的 Cursor.Position 减去 e.Location 得到的始终是事件源的 Location
*/
2、不移动控件本身,创建新控件做幻影移动
public partial class Form1 : Form
{
/// <summary>
/// 鼠标按下为true
/// </summary>
private bool Mousedown;
/// <summary>
/// 鼠标在事件源的位置
/// </summary>
private int CurX = 0;
private int CurY = 0;
[DllImport("user32.dll")]
private static extern IntPtr WindowFromPoint(Point p);//获取当前鼠标光标所在的控件的句柄
Label labelTemp = new Label();
public Form1()
{
InitializeComponent();
labelTemp.ForeColor = Color.Red;
//labelTemp.Text = "testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest";
labelTemp.Font = new Font("宋体", 21.75F, FontStyle.Bold, GraphicsUnit.Point, (byte)(134));
labelTemp.Size = new Size(109, 29);
labelTemp.BackColor = Color.Transparent;
this.Controls.Add(labelTemp);
labelTemp.Visible = false;
}
private void a_MouseDown(object sender, MouseEventArgs e)
{
CurX = e.X;
CurY = e.Y;
Mousedown = true;
labelTemp.Visible = true;
if (sender is Label)
{
labelTemp.Text = (sender as Label).Text;
}
labelTemp.BringToFront();
}
private void a_MouseMove(object sender, MouseEventArgs e)
{
if (Mousedown)
{
// 获取当前屏幕的光标坐标
Point pTemp = new Point(Cursor.Position.X, Cursor.Position.Y);
// 转换成工作区坐标
pTemp = this.PointToClient(pTemp);
// 定位事件源的 Location
labelTemp.Location = new Point(pTemp.X - CurX, pTemp.Y - CurY);
}
}
private void a_MouseUp(object sender, MouseEventArgs e)
{
Mousedown = false;
labelTemp.Visible = false;
Point p = Cursor.Position;
IntPtr h = WindowFromPoint(p);
SetMouseUpControl(h, this);
}
private void SetMouseUpControl(IntPtr h,Control control)
{
if (control.Controls.Count < 1)
{
if (control.Handle==h)
{
control.Text = labelTemp.Text;
}
return;
}
foreach (Control con in control.Controls)
{
SetMouseUpControl(h, con);
}
}
}
3、其它方式
3.1、移动控件本身
见作者的另一篇文章 —— 移动控件