Visio中的Undo和Redo

时间:2023-03-09 19:31:39
Visio中的Undo和Redo

1.Visio默认Undo和Redo操作是可用的,Appliacation中的UndoEnabled标志Undo和Redo操作是否可用。

m_Visio.Window.Application.UndoEnabled = True

当 Microsoft Visio 启动时,UndoEnabled 属性的值为 True。将 UndoEnabled 属性的值设置为 False 会停止在内存中收集撤消信息,并清除现有的撤消信息。

2.Visio中启动事务,结束事务

Dim vsoTextShape As Visio.Shape
Dim UndoScopeID1 As Long
UndoScopeID1 = m_Visio.Window.Application.BeginUndoScope("添加文本形状")
Set vsoTextShape = m_Visio.Window.Application.ActiveWindow.Page.DrawRectangle(X2, Y2, X2 + 1, Y2 - 0.5)
vsoTextShape.TextStyle = "Normal"
vsoTextShape.LineStyle = "Text Only"
vsoTextShape.FillStyle = "Text Only"
vsoTextShape.CellsSRC(visSectionCharacter, 0, visCharacterColor).FormulaU = "2"
vsoTextShape.CellsSRC(visSectionCharacter, 0, visCharacterSize).FormulaU = "8 pt"
vsoTextShape.Characters = "两个输出不可连接"
m_Visio.Window.Application.EndUndoScope UndoScopeID1, True

这样在Undo和Redo操作时,添加文本形状,则以一个整体进行Undo和Redo记录操作,而不会把单元格属性等改变进行单独记录。

3.Visio中撤销所有的Undo队列,Application.PurgeUndo

m_Visio.Window.Application.PurgeUndo

4.操作排队开始事件和结束事件

Private Sub vsoApplication_EnterScope(ByVal app As Visio.IVApplication, ByVal nScopeID As Long, ByVal bstrDescription As String)
'排队内部命令开始时,或当自动化客户端通过使用BeginUndoScope方法打开一个作用域。
' MsgBox (bstrDescription)
End Sub Private Sub vsoApplication_ExitScope(ByVal app As Visio.IVApplication, ByVal nScopeID As Long, ByVal bstrDescription As String, ByVal bErrOrCancelled As Boolean)
'排队内部命令结束时,或当自动化客户端通过使用EndUndoScope方法退出范围。
' MsgBox (bstrDescription)
End Sub

5.清空消息队列事件

Private Sub vsoApplication_VisioIsIdle(ByVal app As Visio.IVApplication)

End Sub

Visio 将不断地处理其消息队列中的消息。当其消息队列为空时:

  • Visio 将执行自己的空闲时间处理。

  • Visio 将告知 Microsoft Visual Basic for Applications 来执行它的空闲时间处理。

  • 如果消息队列仍然为空,Visio 将触发 VisioIsIdle 事件。

  • 如果消息队列仍然为空,Visio 将调用 WaitMessage,这是对 Microsoft Windows 的调用,在将新消息添加到 Visio 消息队列中之前,将不会返回。

客户端程序可以使用 VisioIsIdle 事件作为执行自己的后台处理的信号。

VisioIsIdle 事件与标准的计时器事件并不等效。需要定期调用的客户端程序应使用标准的计时器技术,因为 Visio 处于空闲状态的持续时间(调用 WaitMessage)不可预测。但是对于只监控 Visio 活动的客户端程序,使用 VisioIsIdle 事件便已足够,因为在WaitMessage 返回到 Visio 之前,自上次触发 VisioIsIdle 事件以来不能有任何 Visio 活动。

6.确定是否调用事件处理程序之间的EnterScope事件和作用域的ExitScope事件 Application.IsInScope

代表范围 ID 的常量以 visCmd 为前缀并由 Visio 类型库声明。您也可以使用由 BeginUndoScope 方法返回的 ID。

您可以在 CellChanged 事件处理程序中使用此属性来确定单元格更改是否是特定操作的结果。

7.确定引起事件触发的范围 ID Application.CurrentScope

Private WithEvents vsoApplication As Visio.Application
Private lngScopeID As Long Public Sub ScopeActions() Dim vsoShape As Visio.Shape 'Set the module level application variable to
'trap Application level events.Set vsoApplication = Application 'Begin a scope, set the module level variable.lngScopeID = Application.BeginUndoScope("Draw Shapes") 'Draw three shapes.Set vsoShape = ActivePage.DrawRectangle(1, 2, 2, 1)
ActivePage.DrawOval 3, 4, 4, 3
ActivePage.DrawLine 4, 5, 5, 4 'Change a cell (which would trigger a cell changed event).vsoShape.Cells("Width").Formula = 5 'End and commit this scope.Application.EndUndoScope lngScopeID, True End Sub Private Sub vsoApplication_CellChanged(ByVal Cell As IVCell) 'Check to see if this cell change is the result of something
'happening within the scope.If vsoApplication.IsInScope(lngScopeID) Then
Debug.Print Cell.Name & " changed in scope "; lngScopeID
End If End Sub Private Sub vsoApplication_EnterScope(ByVal app As IVApplication, _
ByVal nScopeID As Long, _
ByVal bstrDescription As String) If vsoApplication.CurrentScope = lngScopeID Then
Debug.Print "Entering current scope " & nScopeID
Else
Debug.Print "Enter Scope " & bstrDescription & "(" & nScopeID & ")"
End If End Sub Private Sub vsoApplication_ExitScope(ByVal app As IVApplication, _
ByVal nScopeID As Long, _
ByVal strDescription As String, _
ByVal bErrOrCancelled As Boolean) If vsoApplication.CurrentScope = lngScopeID Then
Debug.Print "Exiting current scope " & nScopeID
Else
Debug.Print "ExitScope " & bstrDescription & "(" & nScopeID & ")"
End If End Sub

如果范围没有打开,则返回 visScopeIDInvalid (-1)。范围 ID 可以是对应于 Visio 命令的内部 Microsoft Visio 范围 ID,也可以是由 BeginUndoScope 方法传递给自动化客户机的外部范围 ID。

如果 EnterScope 事件已经触发而 ExitScope 事件却尚未触发,则事件的接收方会认为范围处于打开状态。

要确定事件队列的触发是与应用程序内部的特定范围相关,还是与自动化客户机打开或关闭的范围相关,请使用 IsInScope 属性。

8.Undo和Redo操作

m_Visio.Window.Application.Undo
m_Visio.Window.Application.Redo

使用 Undo 方法一次取消撤消单元的一个动作。

代码可以调用 Undo 方法的次数取决于代码是否在打开的撤消单元范围内执行。在下列任一情况下,代码将在打开的撤消单元范围内运行:

  • 由 Microsoft Visio 用户界面调用宏或加载项。

  • 事件处理程序响应 Visio 事件而不是 VisioIsIdle 事件。

  • 在用户创建的撤消范围中。

如果代码不打开的撤消单元范围内执行的它可以对目前 Visio 撤消堆栈上的每个撤消单元调用Undo方法。您可以设置在撤消堆栈上的最大单位数 (20 是默认值) 上的选项对话框的高级选项卡 (单击文件选项卡,然后单击选项)。如果将Undo方法的调用次数超过堆栈上的撤消单元的数字,不执行任何操作, Undo方法不会引发异常。

如果代码是在打开的撤消单元范围内执行的,它可以对打开的撤消单元中的每个操作调用一次 Undo 方法。如果另外还要调用 Undo 方法,它将引发异常并且不执行任何动作。例如,如果宏中的代码执行两个操作,它可以调用 Undo 方法两次。当该宏第三次调用 Undo方法时,Undo 方法将引发异常。

从撤消单元范围内调用 Undo 方法的代码不能调用 Redo 方法来取消动作。仅当不存在打开的撤消单元时,才可以调用 Redo 方法。

如果 Visio 实例当前正在执行撤消或恢复操作,Undo 方法也将引发异常。要确定 Visio 实例是否正在撤消或恢复,请使用 IsUndoingOrRedoing 属性。

您可以从 VisioIsIdle 事件处理程序调用 Undo 方法,因为仅当 IsUndoingOrRedoing 属性为 False 时才能触发 VisioIsIdle 事件。您也可以从非 Visio 实例调用的代码(例如,从 Visual Basic 编辑器或外部程序调用的代码)调用 Undo 方法。

您可以撤消大多数动作,但不能撤消全部。使用 Redo 方法来取消 Undo 方法的效果。