Home
Search
 
What's New
Index
Books
Links
Q & A
Newsletter
Banners
 
Feedback
Tip Jar
 
C# Helper...
 
XML RSS Feed
Follow VBHelper on Twitter
 
 
MSDN Visual Basic Community
 
 
 
 
 
 
TitleImplement multi-level Undo and Redo commands
Keywordsundo, redo
CategoriesSoftware 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
 
 
Copyright © 1997-2010 Rocky Mountain Computer Consulting, Inc.   All rights reserved.
  Updated