Visual C ++撤消和重做操作

时间:2012-04-28 21:09:45

标签: c++ visual-c++ c++-cli undo-redo

我有一个相当大的应用程序我想在Visual-C ++中创建,我现在正在尝试添加撤消/重做功能。

有相当多的事件(按钮点击,标签文本更改等),我想找到一种方法来撤消/重做而不向每个函数添加代码。 对于Instance,我想要一个可以读取每个事件并自动存储的类。然后在我的undo / redo事件中,我可以将最新的动作存储起来。

如果那是不可能的,我不介意其他方式。

任何帮助?

3 个答案:

答案 0 :(得分:2)

声明一个代表两个操作的类 - 撤消和重做。 同时创建该类的两个向量。

对于要应用undo / redo的每个操作,将该类的实例推送到撤消向量中。应该有与要撤消的操作一样多的派生类。

例如,如果单击按钮将背景绘制为绿色,则会创建一个类实例,其撤消metdho将背景绘制为前一种颜色,其重做方法将背景绘制为绿色,并将其填充到撤消向量中。 撤消时 - 弹出最后一个类实例并调用其undo方法,该方法将背景绘制为上一个颜色。然后你把它推到重做矢量。

当你重做时,你在顶部弹出类实例的重做向量并调用它的重做方法,然后将它重新填充到撤消向量。

有一些极端情况(边界),遇到时你会解决它们:.. - )

答案 1 :(得分:1)

您的所有活动是否都通过了某种类型的队列?默认情况下,在c ++中没有这样的队列(有一个windows os级别事件队列,但是很可能已经管理并且在c ++中无法使用 - cli并且你没有指出这是否紧密映射到你的问题上),可能有一些其他构造我不知道。

如果您有一些中央队列,那么只需捕获事件并在知道如何撤消每个操作时捕获事件。如果没有中央队列,那么除了改变每个可撤销功能以创建某种撤销对象并将其存储在某种撤销队列中之外,我认为没有别的办法了。

在没有大型中央工作队列的纯.net或C ++环境中,我会创建一个类和undo entry,它实现一个方法/成员函数来撤消,另一个实现重做/完成工作。但是对于撤消功能,这可能只是一个.net委托或一个c样式函数指针,以及一个参数列表。如果你做一个动作undo / redo类,它可以是一个模板或泛型,它存储指向do和undo函数的指针/委托,以及一个从最初调用它时的参数列表。

可以运行这些操作来撤消已完成的操作。它们将被插入到某种类型的队列容器中,这种容器看起来并不重要,只要它保留顺序,你应该为你的应用选择最好的std,.net或其他容器。当您不再需要它们时,您可以丢弃旧的。执行时,必须删除最后插入队列的条目以保持一致性。

如果您还需要重做功能,那么您完成的操作队列必须是可迭代的,并且最简单的方法是使用该类,并且操作具有可以撤消/重做所需操作的方法/成员函数。你会得到某种迭代器,指针,索引或标记,表明你已经撤消了多远。每次请求撤消时,您必须向后移动标记(按时间顺序排列)并在队列中的该点执行撤消命令。如果请求重做,则指示的当前项执行其重做指令,然后迭代器通过队列向前(按时间顺序)前进,或者如果您位于队列中最前面的项目,则忽略(我假设)。

如果你想离开你想要的无法指出的深层,你可以将你的应用程序围绕在行动队列中。您可能不需要更改实现此方法的功能。您的用户界面(我假设,可以很容易就是您的API)功能,将操作(支持执行和撤消)插入队列,然后命令队列执行。如果已知副作用且可逆,则无需更改现有功能。但是,您需要更改所有调用者以执行操作而不是直接调用,并且您需要编写执行撤消操作的对应方。

答案 2 :(得分:1)

我试图在一个小型实验库中实现类似的东西:https://github.com/d-led/undoredo-cpp。它包含TransactionStore的实现,类似于 CodeChords man 建议的实现。您可能需要为每个可撤销对象添加功能,并且还要处理对象生命周期,以防您的操作涉及对象构造或销毁