Imports System.Runtime.InteropServices
Public Class Form1
Private Structure restorePoint
Dim scrollPosition As Point
Dim RTF As String
End Structure
Dim undoStack As New Stack(Of restorePoint)
Dim redoStack As New Stack(Of restorePoint)
Private Sub BoldToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BoldToolStripMenuItem.Click
undoStack.Push(New restorePoint With {.scrollPosition = getScrollPosition(), .RTF = RichTextBox1.Rtf})
btnUndo.Enabled = undoStack.Count > 0
RichTextBox1.SelectionFont = New Font(RichTextBox1.SelectionFont, RichTextBox1.SelectionFont.Style Or FontStyle.Bold)
End Sub
Private Sub ItalicToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ItalicToolStripMenuItem.Click
undoStack.Push(New restorePoint With {.scrollPosition = getScrollPosition(), .RTF = RichTextBox1.Rtf})
btnUndo.Enabled = undoStack.Count > 0
RichTextBox1.SelectionFont = New Font(RichTextBox1.SelectionFont, RichTextBox1.SelectionFont.Style Or FontStyle.Italic)
End Sub
Private Sub UnderlineToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles UnderlineToolStripMenuItem.Click
undoStack.Push(New restorePoint With {.scrollPosition = getScrollPosition(), .RTF = RichTextBox1.Rtf})
btnUndo.Enabled = undoStack.Count > 0
RichTextBox1.SelectionFont = New Font(RichTextBox1.SelectionFont, RichTextBox1.SelectionFont.Style Or FontStyle.Underline)
End Sub
Private Sub ColorToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ColorToolStripMenuItem.Click
If ColorDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
undoStack.Push(New restorePoint With {.scrollPosition = getScrollPosition(), .RTF = RichTextBox1.Rtf})
btnUndo.Enabled = undoStack.Count > 0
RichTextBox1.SelectionColor = ColorDialog1.Color
End If
End Sub
Private Sub FontToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles FontToolStripMenuItem.Click
If FontDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
undoStack.Push(New restorePoint With {.scrollPosition = getScrollPosition(), .RTF = RichTextBox1.Rtf})
btnUndo.Enabled = undoStack.Count > 0
RichTextBox1.SelectionFont = FontDialog1.Font
End If
End Sub
Private Sub InsertImageToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles InsertImageToolStripMenuItem.Click
Dim ofd As New OpenFileDialog
ofd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)
If ofd.ShowDialog = Windows.Forms.DialogResult.OK Then
Dim img As New Bitmap(ofd.FileName)
Clipboard.SetImage(img)
undoStack.Push(New restorePoint With {.scrollPosition = getScrollPosition(), .RTF = RichTextBox1.Rtf})
btnUndo.Enabled = undoStack.Count > 0
RichTextBox1.Paste()
End If
End Sub
Private Sub RichTextBox1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles RichTextBox1.KeyDown
If e.KeyCode = Keys.Space Then
undoStack.Push(New restorePoint With {.scrollPosition = getScrollPosition(), .RTF = RichTextBox1.Rtf})
btnUndo.Enabled = undoStack.Count > 0
End If
End Sub
Private Sub btnUndo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnUndo.Click
redoStack.Push(New restorePoint With {.scrollPosition = getScrollPosition(), .RTF = RichTextBox1.Rtf})
Dim rp As restorePoint = undoStack.Pop
RichTextBox1.Rtf = rp.RTF
setScrollPosition(rp.scrollPosition)
btnUndo.Enabled = undoStack.Count > 0
btnRedo.Enabled = redoStack.Count > 0
End Sub
Private Sub btnRedo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRedo.Click
undoStack.Push(New restorePoint With {.scrollPosition = getScrollPosition(), .RTF = RichTextBox1.Rtf})
Dim rp As restorePoint = redoStack.Pop
RichTextBox1.Rtf = rp.RTF
setScrollPosition(rp.scrollPosition)
btnUndo.Enabled = undoStack.Count > 0
btnRedo.Enabled = redoStack.Count > 0
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
undoStack.Push(New restorePoint With {.scrollPosition = getScrollPosition(), .RTF = RichTextBox1.Rtf})
End Sub
Public Declare Function GetScrollInfo Lib "user32" Alias "GetScrollInfo" (ByVal hWnd As IntPtr, _
ByVal n As Integer, <MarshalAs(UnmanagedType.Struct)> ByRef lpScrollInfo As SCROLLINFO) As Integer
<StructLayout(LayoutKind.Sequential)> _
Public Structure SCROLLINFO
Public cbSize As Integer
Public fMask As Integer
Public nMin As Integer
Public nMax As Integer
Public nPage As Integer
Public nPos As Integer
Public nTrackPos As Integer
End Structure
Const SBS_HORZ As Integer = 0
Const SBS_VERT As Integer = 1
Const SIF_RANGE As Integer = 1
Const SIF_PAGE As Integer = 2
Const SIF_POS As Integer = 4
Const SIF_TRACKPOS As Integer = 10
Const SIF_ALL As Integer = (SIF_RANGE Or SIF_PAGE Or SIF_POS Or SIF_TRACKPOS)
Private Function getScrollPosition() As Point
Dim si As New SCROLLINFO
si.fMask = SIF_ALL
si.cbSize = Marshal.SizeOf(si)
GetScrollInfo(RichTextBox1.Handle, SBS_HORZ, si)
Dim x As Integer = si.nPos
si = New SCROLLINFO
si.fMask = SIF_ALL
si.cbSize = Marshal.SizeOf(si)
GetScrollInfo(RichTextBox1.Handle, SBS_VERT, si)
Dim y As Integer = si.nPos
Return New Point(x, y)
End Function
Private Declare Function SetScrollInfo Lib "user32.dll" ( _
ByVal hWnd As IntPtr, ByVal nBar As Integer, _
ByVal lpScrollInfo As SCROLLINFO, _
ByVal fRedraw As Boolean) As Integer
Private Sub setScrollPosition(ByVal scrollValue As Point)
Dim si As New SCROLLINFO
si.nPos = scrollValue.X
si.cbSize = Marshal.SizeOf(si)
SetScrollInfo(RichTextBox1.Handle, SBS_HORZ, si, True)
si = New SCROLLINFO
si.nPos = scrollValue.Y
si.cbSize = Marshal.SizeOf(si)
SetScrollInfo(RichTextBox1.Handle, SBS_VERT, si, True)
End Sub
End Class