在运行时使用鼠标移动和调整窗体上的控件






4.98/5 (55投票s)
在运行时(使用鼠标)移动和调整窗体上的控件

引言
有时,我们希望在运行时移动和调整控件,例如,当我们想要为窗体创建一些模板时。网上有一些关于此的代码,但它们无法同时进行移动和调整大小。因此,我在另一篇CodeProject文章的基础上编写了自己的类。
使用此类,我们只需一行代码即可创建可调整大小和可移动的控件
ControlMoverOrResizer.Init(button1);
真的吗? 是的!! :)
背景
此类在事件处理程序分配中使用 lambda 表达式。
internal static void Init(Control control, Control container)
{
_moving = false;
_resizing = false;
_moveIsInterNal = false;
_cursorStartPoint = Point.Empty;
MouseIsInLeftEdge = false;
MouseIsInLeftEdge = false;
MouseIsInRightEdge = false;
MouseIsInTopEdge = false;
MouseIsInBottomEdge = false;
WorkType = MoveOrResize.MoveAndResize;
control.MouseDown += (sender, e) => StartMovingOrResizing(control, e);
control.MouseUp += (sender, e) => StopDragOrResizing(control);
control.MouseMove += (sender, e) => MoveControl(container, e);
}
我将所有字段、属性和方法编写为static
;因此,不需要创建ControlMoverOrResizer
类的对象。
internal class ControlMoverOrResizer
{
private static bool _moving;
private static Point _cursorStartPoint;
private static bool _moveIsInterNal;
private static bool _resizing;
private static Size _currentControlStartSize;
internal static bool MouseIsInLeftEdge { get; set; }
internal static bool MouseIsInRightEdge { get; set; }
internal static bool MouseIsInTopEdge { get; set; }
internal static bool MouseIsInBottomEdge { get; set; }
internal enum MoveOrResize ...
internal static MoveOrResize WorkType { get; set; }
internal static void Init(Control control) ...
internal static void Init(Control control, Control container) ...
private static void UpdateMouseEdgeProperties(Control control, Point mouseLocationInControl) ...
private static void UpdateMouseCursor(Control control) ...
private static void StartMovingOrResizing(Control control, MouseEventArgs e) ...
private static void MoveControl(Control control, MouseEventArgs e) ...
private static void StopDragOrResizing(Control control) ...
}
类中唯一不是private
的方法是init
方法。 当将控件(或两个及其容器)发送到init
方法时,它会将相关方法添加到 3 个重要的控件事件。
control.MouseDown += (sender, e) => StartMovingOrResizing(control, e);
control.MouseUp += (sender, e) => StopDragOrResizing(control);
control.MouseMove += (sender, e) => MoveControl(container, e);
现在,当用户在控件上按下鼠标时,事件会调用StartMovingOrResizing
方法,并且此方法将设置控件的movingMode
或resizingMode
private static void StartMovingOrResizing(Control control, MouseEventArgs e)
{
if (_moving || _resizing)
{
return;
}
if (WorkType!=MoveOrResize.Move &&
(MouseIsInRightEdge || MouseIsInLeftEdge || MouseIsInTopEdge || MouseIsInBottomEdge))
{
_resizing = true;
_currentControlStartSize = control.Size;
}
else if (WorkType!=MoveOrResize.Resize)
{
_moving = true;
control.Cursor = Cursors.Hand;
}
_cursorStartPoint = new Point(e.X, e.Y);
control.Capture = true;
}
当用户在控件上移动鼠标光标时,将调用MoveControl
方法,此方法调用UpdateMouseEdgeProperties
和UpdateMouseCursor
函数。
UpdateMouseEdgeProperties
将检查哪个光标位于控件的任何边缘上,并将设置相关的属性
private static void UpdateMouseEdgeProperties(Control control, Point mouseLocationInControl)
{
if (WorkType == MoveOrResize.Move)
{
return;
}
MouseIsInLeftEdge = Math.Abs(mouseLocationInControl.X) <= 2;
MouseIsInRightEdge = Math.Abs(mouseLocationInControl.X - control.Width) <= 2;
MouseIsInTopEdge = Math.Abs(mouseLocationInControl.Y ) <= 2;
MouseIsInBottomEdge = Math.Abs(mouseLocationInControl.Y - control.Height) <= 2;
}
并且,如果鼠标光标位于控件的边缘,UpdateMouseCursor
函数将更改鼠标光标
private static void UpdateMouseCursor(Control control)
{
if (WorkType == MoveOrResize.Move)
{
return;
}
if (MouseIsInLeftEdge )
{
if (MouseIsInTopEdge)
{
control.Cursor = Cursors.SizeNWSE;
}
else if (MouseIsInBottomEdge)
{
control.Cursor = Cursors.SizeNESW;
}
else
{
control.Cursor = Cursors.SizeWE;
}
}
else if (MouseIsInRightEdge)
{
if (MouseIsInTopEdge)
{
control.Cursor = Cursors.SizeNESW;
}
else if (MouseIsInBottomEdge)
{
control.Cursor = Cursors.SizeNWSE;
}
else
{
control.Cursor = Cursors.SizeWE;
}
}
else if (MouseIsInTopEdge || MouseIsInBottomEdge)
{
control.Cursor = Cursors.SizeNS;
}
else
{
control.Cursor = Cursors.Default;
}
}
现在,程序将回调到MoveControl
函数,并在此方法中继续。它将检查_resizing
字段(此字段将在使用pressDown
鼠标在控件边缘上并保持按下状态时设置)。
如果控件处于调整大小模式,则光标所在的控件边缘会随着光标移动
if (_resizing)
{
if (MouseIsInLeftEdge)
{
if (MouseIsInTopEdge)
{
control.Width -= (e.X - _cursorStartPoint.X);
control.Left += (e.X - _cursorStartPoint.X);
control.Height -= (e.Y - _cursorStartPoint.Y);
control.Top += (e.Y - _cursorStartPoint.Y);
}
else if (MouseIsInBottomEdge)
{
control.Width -= (e.X - _cursorStartPoint.X);
control.Left += (e.X - _cursorStartPoint.X);
control.Height = (e.Y - _cursorStartPoint.Y)
+ _currentControlStartSize.Height;
}
else
{
control.Width -= (e.X - _cursorStartPoint.X);
control.Left += (e.X - _cursorStartPoint.X) ;
}
}
else if (MouseIsInRightEdge)
{
if (MouseIsInTopEdge)
{
control.Width = (e.X - _cursorStartPoint.X)
+ _currentControlStartSize.Width;
control.Height -= (e.Y - _cursorStartPoint.Y);
control.Top += (e.Y - _cursorStartPoint.Y);
}
else if (MouseIsInBottomEdge)
{
control.Width = (e.X - _cursorStartPoint.X)
+ _currentControlStartSize.Width;
control.Height = (e.Y - _cursorStartPoint.Y)
+ _currentControlStartSize.Height;
}
else
{
control.Width = (e.X - _cursorStartPoint.X)
+_currentControlStartSize.Width;
}
}
else if (MouseIsInTopEdge)
{
control.Height -= (e.Y - _cursorStartPoint.Y);
control.Top += (e.Y - _cursorStartPoint.Y);
}
else if (MouseIsInBottomEdge)
{
control.Height = (e.Y - _cursorStartPoint.Y)
+ _currentControlStartSize.Height;
}
else
{
StopDragOrResizing(control);
}
}
否则,如果控件处于移动模式(当用户在控件内部按下鼠标并保持按下状态时,控件将进入移动模式),则控件的位置将随光标移动
else if (_moving)
{
_moveIsInterNal = !_moveIsInterNal;
if (!_moveIsInterNal)
{
int x = (e.X - _cursorStartPoint.X) + control.Left;
int y = (e.Y - _cursorStartPoint.Y) + control.Top;
control.Location = new Point(x, y);
}
}
最后,当用户释放鼠标时,将调用StopDragOrResizing
方法,它会将移动模式和调整大小模式重置为false
并更新光标。
private static void StopDragOrResizing(Control control) { _resizing = false; _moving = false; control.Capture = false; UpdateMouseCursor(control); }
Using the Code
为了启用控件的调整大小和移动模式,我们只需在MoveAndResizeControls
类中调用init
方法,并将控件发送给它。
MoveAndResizeControls.Init(button1);
如果我们想要更改控件的容器(例如,当控件填充到其容器中时),我们只需将容器作为第二个参数发送。
ControlMoverOrResizer.Init(button2,panel1);
在某些情况下,我们只需要调整大小或移动控件中的一个,在这种情况下,我们只需使用以下值之一设置ControlMoverOrResizer
类中的WorkType
属性
internal enum MoveOrResize
{
Move,
Resize,
MoveAndResize
}
在此处上传的演示示例中,可以通过鼠标移动和调整控件的大小。此外,演示窗体中有一个组合框,它可以帮助您选择工作类型(“移动”、“调整大小”或“移动和调整大小”)。
using System;
using System.Windows.Forms;
using ControlManager;
namespace MoveAndResizeControls
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
ControlMoverOrResizer.Init(button1);
ControlMoverOrResizer.Init(groupBox1);
ControlMoverOrResizer.Init(textBox1);
ControlMoverOrResizer.Init(button2,panel1);
comboBox1.SelectedIndex = 0;
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
switch (comboBox1.SelectedIndex)
{
case 0:
ControlMoverOrResizer.WorkType=ControlMoverOrResizer.MoveOrResize.MoveAndResize;
break;
case 1:
ControlMoverOrResizer.WorkType = ControlMoverOrResizer.MoveOrResize.Move;
break;
case 2:
ControlMoverOrResizer.WorkType = ControlMoverOrResizer.MoveOrResize.Resize;
break;
}
}
}
}
关注点
如果您想保存和加载更改,可以使用以下方法
GetSizeAndPositionOfControlsToString
SetSizeAndPositionOfControlsFromString
这是移动和调整控件大小后的窗体
衷心感谢您的时间和考虑。
祝您一切顺利。
历史
- 2014/01/10:截至发布时,版本 1.0.0.0
- 2014/02/09:截至更新时,版本 1.1.0.0