0

我有一个 WinForms 图像/绘画应用程序。

该应用程序允许用户执行以下操作:

  • 加载/导入图像
  • 保存图片
  • 旋转,裁剪图像
  • 更改像素或区域的颜色

如何以有效的方法为多个操作实现撤消/重做功能?我应该处理哪个鼠标事件?

我想避免将整个内容保存在图片框中(加载图像的位置),因为它可能会消耗大量内存。

谢谢你。

4

1 回答 1

2

我见过的实现撤消/重做的最佳方式是使用“命令”模式。

每个可以执行的操作都应该作为一个类来实现,要么继承自基Command类,要么实现ICommand接口。该类应该有一个Execute和一个Undo方法,在其中Execute对数据执行操作,并存储撤消操作所需的任何信息。Undo使用存储的有关要撤消的更改的信息。

如果您只想要一个简单的系统,您只能撤消/重做最后一个操作,只需保留一个lastCommand存储最后一个运行命令的字段,并Undo在需要时调用它。

如果你想要更复杂的东西,具有多级撤消,请保留一个有序的命令列表,你可以将其视为Stack. 每个执行Command的都被执行,并被放置在堆栈的顶部,一些变量指向最后一个命令。当您撤消操作时,调用Undoon lastCommand,然后将其设置为Command之前的。要重做操作,只需Execute再次调用下一个命令,然后向上移动指针。您必须确保Command当您不在堆栈的“顶部”时运行的任何操作都会使其无效并删除它之前的操作。

您可以变得更高级,如果您愿意,可以将命令等花哨的东西合并在一起。


Command举一个可以改变单个像素的事情的例子(全部来自内存,无法访问 Visual Studio,所以请原谅任何语法错误)。

由于您没有指定语言,我将使用 C#,但这也可以在 VB.NET 中轻松完成。

public class ChangePixelCommand : ICommand
{    
    private Color _previousColor;
    private int x;
    private int y;

    public void Execute(Bitmap image, int x, int y, Color color)
    {
        // record the data needed to undo this operation.
        _previousColor = image.GetPixel(x, y);
        _x = x;
        _y = y;

        // update the image.
        image.SetPixel(x, y, color);
    }

    public void Undo(Bitmap image)
    {
        //  Use the data we saved earlier to put the pixel back the way it was.
        image.SetPixel(_x, _y, _previousColor);
    }
}

要在上面的“简单”方法中使用它,您只需执行以下操作:

// Change a pixel.
lastCommand = new ChangePixelCommand(myImage, 
                                     Control.MousePosition.X,
                                     Control.MousePosition.Y, 
                                     Colors.Red);
lastCommand.Execute();

// Undo the change
lastCommand.Undo();

要更改区域,您可以仅存储更改的矩形的边界,以及该区域以前的样子的小快照。

对于旋转,它只是通过旋转角度。

我不确定为什么你们任何人都想“撤消”保存,但如果你真的需要,你可以存储文件名并删除文件。虽然恢复文件的先前内容......这可能会变得很棘手。

于 2018-03-12T12:37:20.317 回答