我有两个自定义Control
类,Box
和Ellipse
。我能够绘制,拖动和调整它们的大小。现在我尝试实现无限制的撤销和重做。我为此使用了Command Pattern
。我的Box
类看起来与Ellipse
类完全相同,区别在于Box
类描绘了一个盒子形状。在我绘制Ellipse
并且例如移动/调整此控件的时刻,我能够退后一步,因为添加使堆栈大小为1,而一次撤消使堆栈大小再次为0。只有当我添加Ellipse
时,我才会立即将命令推送到Stack
。调整大小/移动发生在另一个类然后添加,但这些操作也必须推送到commandStack
中的Form1
。我怎么能这样做?
我的想法是在Ellipse
和Box
中创建一个堆栈,并为每个操作调用Do
并将每个命令推送到堆栈(在Ellipse
或{{1 }}),但这不会起作用我相信因为Box
类需要使用来自所有Form
的所有命令来访问堆栈。有谁可以帮助进行无限制的撤销/重做工作?
我按照此链接中的示例进行了操作:http://www.c-sharpcorner.com/uploadfile/40e97e/command-pattern-undo-example/。
ICommand界面
Controls
椭圆类
public interface ICommand
{
void Do();
void Undo();
}
表单类
class Ellipse : Control, ICommand
{
private Point mDown { get; set; }
public Ellipse()
{
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.BackColor = Color.Transparent;
this.DoubleBuffered = true;
this.ResizeRedraw = true;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
// Draw a black ellipse in the rectangle represented by the control.
e.Graphics.FillEllipse(Brushes.Black, 0, 0, Width, Height);
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
mDown = e.Location;
}
protected override void OnMouseMove(MouseEventArgs e)
{
// Call MyBase.OnMouseMove to activate the delegate.
base.OnMouseMove(e);
if (e.Button == MouseButtons.Left)
{
Location = new Point(e.X + Left - mDown.X, e.Y + Top - mDown.Y);
}
}
/* Allow resizing at the bottom right corner */
protected override void WndProc(ref Message m)
{
const int wmNcHitTest = 0x84;
const int htBottomLeft = 16;
const int htBottomRight = 17;
if (m.Msg == wmNcHitTest)
{
int x = (int)(m.LParam.ToInt64() & 0xFFFF);
int y = (int)((m.LParam.ToInt64() & 0xFFFF0000) >> 16);
Point pt = PointToClient(new Point(x, y));
Size clientSize = ClientSize;
if (pt.X >= clientSize.Width - 16 && pt.Y >= clientSize.Height - 16 && clientSize.Height >= 16)
{
m.Result = (IntPtr)(IsMirrored ? htBottomLeft : htBottomRight);
return;
}
}
base.WndProc(ref m);
}
int x;
int y;
int height;
int width;
private void SaveCurrentControl()
{
x = this.Left;
y = this.Top;
height = this.Height;
width = this.Width;
}
public void Do()
{
SaveCurrentControl();
}
public void Undo()
{
this.Left = x;
this.Top = y;
this.Height = height;
this.Width = width;
}
}