IOleUndoManager 接口 (ocidl.h)

IOleUndoManager 接口使容器能够为包含在控件内发生的操作实现多级撤消和重做操作。

继承

IOleUndoManager 接口继承自 IUnknown 接口。 IOleUndoManager 还具有以下类型的成员:

方法

IOleUndoManager 接口具有以下方法。

 
IOleUndoManager::Add

将简单的撤消单元添加到集合。 当父撤消单元处于打开状态时,撤消管理器通过调用 IOleParentUndoUnit::Add 向其添加撤消单元。
IOleUndoManager::Close

关闭指定的父撤消单元。 (IOleUndoManager.Close)
IOleUndoManager::D iscardFrom

指示撤消管理器在撤消或重做堆栈上放弃指定的撤消单元及其下的所有撤消单元。
IOleUndoManager::Enable

启用或禁用撤消管理器。
IOleUndoManager::EnumRedoable

创建一个枚举器对象,调用方可以使用该对象从重做堆栈中循环访问一系列顶级撤消单元。
IOleUndoManager::EnumUndoable

创建一个枚举器对象,调用方可以使用该对象从撤消堆栈中循环访问一系列顶级撤消单元。
IOleUndoManager::GetLastRedoDescription

检索位于重做堆栈顶部的顶级撤消单元的说明。
IOleUndoManager::GetLastUndoDescription

检索位于撤消堆栈顶部的顶级撤消单元的说明。
IOleUndoManager::GetOpenParentState

检索有关最内部打开的父撤消单元的状态信息。 (IOleUndoManager.GetOpenParentState)
IOleUndoManager::Open

打开一个新的父撤消单元,该撤消单元将成为其包含单元的撤消堆栈的一部分。
IOleUndoManager::RedoTo

指示撤消管理器通过重做堆栈调用撤消操作,并包括指定的撤消单元。
IOleUndoManager::UndoTo

指示撤消管理器通过撤消堆栈调用撤消操作,并包括指定的撤消单元。

注解

控件必须创建具有 IOleUndoUnit 接口的撤消单元,或使用派生自 IOleUndoUnit 的 IOleParentUndoUnit 接口的父撤消单元。 这两个接口都执行撤消操作,并且父撤消单元还可以包含嵌套的撤消单元。

撤消管理器提供集中式撤消和重做服务。 它管理撤消堆栈和重做堆栈上的父撤消单元和简单撤消单元。 无论对象是否为 UI 活动对象,它都可以通过在撤消管理器中调用方法在这些堆栈上存放撤消单位。

然后,集中式撤消管理器具有支持主机应用程序的撤消和重做用户界面所需的数据,并且可以在堆栈已满时逐渐放弃撤消信息。

撤消管理器作为服务实现,对象从 IServiceProvider 接口获取指向 IOleUndoManger 的指针。 它通常由容器实现。 该服务管理两个堆栈:撤消堆栈和重做堆栈,每个堆栈都包含嵌入对象或容器应用程序本身生成的撤消单元。

撤消单位通常是为了响应最终用户执行的操作而生成的。 对象不会为编程事件生成撤消操作。 事实上,编程事件应清除撤消堆栈,因为编程事件可能会使堆栈上的撤消单元做出的假设失效。

当对象的状态发生更改时,它会创建一个撤消单元,该单元封装撤消该更改所需的所有信息。 对象调用撤消管理器中的方法,以将其撤消单元放置在堆栈上。 然后,当最终用户选择撤消操作时,撤消管理器会从堆栈中获取顶部撤消单元,通过调用其 IOleUndoUnit::D o 方法调用其操作,然后释放它。 当最终用户选择恢复操作时,撤消管理器会从堆栈中获取顶部的重做单元,通过调用其 IOleUndoUnit::D o 方法调用其操作,然后释放它。

撤消管理器有三种状态:基本状态、撤消状态和恢复状态。 它以基状态开始。 若要从撤消堆栈执行操作,它会将自身置于撤消状态,在撤消单元上调用 IOleUndoUnit::D o ,并返回到基本状态。 若要从重做堆栈执行操作,它会将自身置于重做状态,在撤消单元上调用 IOleUndoUnit::D o ,并返回到基本状态。

如果撤消管理器在处于基本状态时收到新的撤消单元,则会将单元放置在撤消堆栈上并放弃整个重做堆栈。 当它处于撤消状态时,它会将传入单位置于重做堆栈上。 当它处于重做状态时,它会将它们放置在撤消堆栈上,而不会刷新重做堆栈。

撤消管理器还允许对象从任一堆栈中的任何对象开始放弃撤消或重做堆栈。

主机应用程序确定撤消管理器的范围。 例如,在一个应用程序中,范围可能位于文档级别;为每个文档维护单独的撤消管理器;和 撤消是针对每个文档独立管理的。 但是,另一个应用程序对整个应用程序保留一个撤消管理器,因此保留一个撤消范围。

错误处理

撤消操作失败并使文档处于不稳定状态是撤消管理器、撤消单元和应用程序本身必须协同工作才能避免的。 因此,撤消单元、撤消管理器和使用撤消的应用程序或组件必须符合某些要求。

若要执行撤消操作,撤消管理器对一个或多个撤消单元调用 IOleUndoUnit::D o ,这些撤消单元又可能包含更多单位。 如果层次结构中的某个单元失败,错误最终将到达撤消管理器,该管理器负责尝试将文档的状态回滚到调用最后一个顶级单元之前的状态。 撤消管理器通过在撤消尝试期间添加到重做堆栈的单元上调用 IOleUndoUnit::D o 来执行回滚。 如果回滚也失败,则撤消管理器将被迫放弃所有内容并返回到应用程序。 撤消管理器指示回滚是否成功,并且应用程序可以基于此执行不同的操作,例如重新初始化组件,使其处于已知状态。

向堆栈添加撤消单元的所有步骤都应以原子方式执行。 也就是说,所有步骤都必须成功,否则任何步骤都不应成功。

提供撤消管理器的主机应用程序决定撤消失败时要执行的操作。 至少,它应通知用户失败。 撤消管理器将告知主机应用程序撤消是否成功,以及尝试的回滚是否成功。 如果撤消和回滚都失败,主机应用程序可以为用户提供多个选项,包括立即关闭应用程序。

如果简单撤消单元返回失败,则不得更改任何对象的状态。 这包括重做堆栈的状态或撤消堆栈(如果执行重做)。 如果成功,还需要在重做或撤消堆栈上放置相应的单元。 在调用单元之前和之后,应用程序应保持稳定。

父撤消单元的要求与简单单元相同,但有一个例外。 如果一个或多个子级在另一个子级发生故障之前成功,则父单元必须在重做堆栈上提交其相应的单元,并将失败返回给其父级。 如果没有子级成功,则父单元应仅在进行了需要回滚的状态更改时才提交其重做单元。 例如,假设父单元包含三个简单单元。 前两个成功并将单位添加到重做堆栈,但第三个失败。 此时,父单元提交其重做单元并返回失败。

作为副作用,父单元绝不应进行依赖于其子级成功的状态更改。 这样做将导致回滚行为中断。 如果父单元进行状态更改,则应在调用任何子单元之前执行这些更改。 然后,如果状态更改失败,则它不应提交其重做单元,不应调用任何子级,并且应将失败返回给其父级。

撤消管理器对错误处理有一个主要要求:在撤消或重做失败时尝试回滚。

不符合的对象

不支持多级撤消的对象可能会导致全局撤消服务出现严重问题。 由于无法依赖对象来正确更新撤消管理器,因此其他对象提交的任何单元也是可疑的,因为它们的单元可能依赖于不符合对象的状态。 尝试撤消符合对象的单位可能不成功,因为不符合对象中的状态不匹配。

若要检测不支持多级撤消的对象,检查OLEMISC_SUPPORTSMULTILEVELUNDO值。 可以参与全局撤消服务的对象将设置此值。

将不带此值的对象添加到用户可见的撤消上下文时,最佳做法是禁用此上下文的撤消用户界面。 或者,可以向用户显示一个对话框,询问他们是否尝试提供部分撤消支持,解决新对象的不符合性问题。

此外,不合规的对象可能会添加到嵌套容器。 在这种情况下,嵌套容器需要通过调用 IOleUndoManager::EnableFALSE 来通知撤消管理器无法再安全地支持撤消。

要求

要求
最低受支持的客户端 Windows 2000 专业版 [桌面应用 |UWP 应用]
最低受支持的服务器 Windows 2000 Server [桌面应用 |UWP 应用]
目标平台 Windows
标头 ocidl.h

另请参阅

IOleParentUndoUnit

IOleUndoUnit