|
|
Title | Implement multi-level Undo and Redo commands |
Keywords | undo, redo |
Categories | Software Engineering |
|
|
Each time the user types a character, create a TextCmd object to record the action and place the object in a simple stack. When the user presses Ctrl-Z, move back one entry in the stack. When the user presses Ctrl-Y, move forward through the stack.
This technique is more powerful with more complex examples that let you perform operations other than simply typing text.
My book Visual Basic Algorithms, Second Edition demonstrates
this and other advanced object-oriented techniques.
|
|
Private Sub Text1_KeyPress(KeyAscii As Integer)
Const KeyTilda = 126 ' The ~ character.
Dim cmd As TextCmd
If KeyAscii = 26 Then ' ^Z
Undo
ElseIf KeyAscii = 25 Then ' ^Y
Redo
ElseIf KeyAscii >= vbKeySpace And _
KeyAscii <= KeyTilda _
Then ' Some visible key.
' Add the new command to Cmds.
Set cmd = New TextCmd
AddCommand cmd
' Give the command the info it needs to work.
cmd.Initialize Text1, Chr$(KeyAscii)
' Apply the command.
cmd.Apply
End If
' We processed the character so discard it.
KeyAscii = 0
End Sub
' Add a command to the list.
Private Sub AddCommand(cmd As Object)
' Remove any undone commands.
Do While Cmds.Count > LastCmd
Cmds.Remove Cmds.Count
Loop
' Add the new command.
Cmds.Add cmd
LastCmd = Cmds.Count
End Sub
' Redo a command.
Private Sub Redo()
If LastCmd >= Cmds.Count Then Exit Sub
LastCmd = LastCmd + 1
Cmds.Item(LastCmd).Apply
End Sub
' Undo a command.
Private Sub Undo()
If LastCmd < 1 Then Exit Sub
Cmds.Item(LastCmd).Undo
LastCmd = LastCmd - 1
End Sub
|
|
The TextCmd class represents a change to some text. The Initialize method saves whatever information is necessary to undo or redo the change. The Undo and Redo methods remove or apply the change.
|
|
' Save information needed to Apply and Undo.
Public Sub Initialize(ctl As TextBox, new_text As String)
Set TextCtl = ctl
NewText = new_text
OldStart = TextCtl.SelStart
OldLength = TextCtl.SelLength
OldText = TextCtl.SelText
End Sub
' Undo the change.
Public Sub Undo()
TextCtl.SelStart = OldStart
TextCtl.SelLength = Len(NewText)
TextCtl.SelText = OldText
End Sub
' Apply the change.
Public Sub Apply()
TextCtl.SelStart = OldStart
TextCtl.SelLength = OldLength
TextCtl.SelText = NewText
End Sub
|
|
|
|
|
|