Another deficiency I've noticed with i00SpellCheck is its inability to properly handle text within a rich-text box that is protected or hidden (invisible). Fortunately, I've figured out a fix for that--which, unfortunately, requires making strategic changes in several code files. First, I'll explain the change in functionality that my modifications will do:
1. It causes the SpellCheckDialog to skip over any and all cases of a word whose text protected or semi-protected, and, unless otherwise directed, any and all cases of a word whose text is hidden or semi-hidden.
2. It prevents context-menu options from being added when the user right-clicks on a word in a rich-text box which is protected/semi-protected.
3. It still draws a wavy line, when that feature is enabled, under "misspelled" words that are wholly or partially protected/hidden. One can use the extension methods below to disable that line-drawing in such cases, but I've found that that slows down the rendering of rich text. If you want to keep wavy lines from appearing under protected/hidden text, you should modify the Drawing.vb file's CustomPaint procedure to invoke parentTextBox.SetRedraw(False) and Dim ScrollPosition As Point = parentTextBox.GetScrollPosition() before it goes through the text, check the value of parentTextBox.GetTextType(LetterIndex, words(iWord).Length) as well as (the already-checked-for) e.Default before drawing a line, then invoke parentTextBox.SetScrollPosition(ScrollPosition) and parentTextBox.SetRedraw(True) after the text is done being parsed. (Better yet, use a Try block with after redrawing is turned off and the scroll position is saved, with the resetting of these attributes occurring the Finally clause in order to ensure that the text box can redraw and is in the correct scroll position after CustomPaint finishes even if an exception occurs during the word-parsing.)
First of changes:
In the SpellCheck\Engine\Extension.vb file, create a new module, named ExtendedTextReading, and move the ExtendedText and FullSelectionLength extension methods thereto. Also, add the SetRedraw, GetScrollPosition, SetScrollPosition, HasFlag, (only included because this method doesn't come automatically with pre-4.0 versions of .NET!), and GetTextType extension methods, and the various Private components--as follows:
#Region "Extended Text Reading"
Public Module ExtendedTextReading
Private Const WM_USER As Int32 = &H400&
Private Const EM_GETSCROLLPOS As Integer = WM_USER + 221, _
EM_SETSCROLLPOS As Integer = WM_USER + 222
Private Const WM_SETREDRAW As Integer = &HB
Private Const HiddenTextSyntax As String = "(^|[^\\])(\\\\)*\\v[^0]", _
ProtectedTextSyntax As String = "(^|[^\\])(\\\\)*\\protect[^0]"
Private HiddenTextChecker As Regex = _
New Regex(HiddenTextSyntax, _
RegexOptions.IgnoreCase Or RegexOptions.Compiled Or RegexOptions.ExplicitCapture), _
ProtectedTextChecker As Regex = _
New Regex(ProtectedTextSyntax, _
RegexOptions.IgnoreCase Or RegexOptions.Compiled Or RegexOptions.ExplicitCapture)
<DllImport("user32.dll")> _
Private Function SendMessage(ByVal hWnd As IntPtr, ByVal msg As Int32, _
ByVal wParam As Int32, ByRef lParam As Point) As Int32
End Function
<DllImport("user32.dll")> _
Private Function SendMessage(ByVal hWnd As IntPtr, ByVal msg As Int32, _
ByVal wParam As Integer, ByVal lParam As Integer) As Int32
End Function
<Flags()> _
Public Enum TypeOfText
Normal = 0
Hidden = 1
[Protected] = 2
End Enum
<System.Runtime.CompilerServices.Extension()> _
Public Function HasFlag(ByVal TextType As TypeOfText, _
ByVal TypeFlag As TypeOfText) As Boolean
Return (TextType And TypeFlag) = TypeFlag
End Function
<System.Runtime.CompilerServices.Extension()> _
Public Function GetScrollPosition(TextBox As TextBoxBase) As Point
Dim RTBScrollPoint As Point = Nothing
SendMessage(TextBox.Handle, EM_GETSCROLLPOS, 0, RTBScrollPoint)
Return RTBScrollPoint
End Function
<System.Runtime.CompilerServices.Extension()> _
Public Sub SetScrollPosition(TextBox As TextBoxBase, _
ByVal RTBScrollPoint As Point)
SendMessage(TextBox.Handle, EM_SETSCROLLPOS, 0, RTBScrollPoint)
End Sub
<System.Runtime.CompilerServices.Extension()> _
Public Sub SetRedrawMode(TextBox As TextBoxBase, _
ByVal OnOrOff As Boolean)
SendMessage(TextBox.Handle, WM_SETREDRAW, CType(OnOrOff, Integer) And 1, 1)
If OnOrOff Then
TextBox.Refresh()
End If
End Sub
<System.Runtime.CompilerServices.Extension()> _
Public Function FullSelectionLength(TextBox As TextBoxBase) As Integer
If TypeOf TextBox IsNot RichTextBox Then
Return TextBox.SelectionLength
End If
Dim RichTextBox As RichTextBox = DirectCast(TextBox, RichTextBox)
Dim TypeRTB As Type = RichTextBox.GetType
Dim fi As FieldInfo = _
TypeRTB.GetField("curSelStart", _
BindingFlags.Instance Or BindingFlags.NonPublic)
Dim nCurSelStart As Integer = CType(fi.GetValue(RichTextBox), Integer)
fi = TypeRTB.GetField("curSelEnd", _
BindingFlags.Instance Or BindingFlags.NonPublic)
Dim nCurSelEnd As Integer = _
Math.Min(CType(fi.GetValue(RichTextBox), Integer), RichTextBox.TextLength)
If nCurSelStart = -1 AndAlso nCurSelEnd = -1 Then
Return 0
Else
Return _
nCurSelEnd - nCurSelStart
End If
End Function
<System.Runtime.CompilerServices.Extension()> _
Public Function ExtendedText(TextBox As TextBoxBase, _
Optional SelectionOnly As Boolean = False) As String
If TypeOf TextBox IsNot RichTextBox Then
If SelectionOnly Then
Return TextBox.SelectedText
Else
Return TextBox.Text
End If
End If
Dim RichTextBox As RichTextBox = DirectCast(TextBox, RichTextBox)
Dim TypeRTB As Type = RichTextBox.GetType
Dim prop As PropertyInfo = _
TypeRTB.GetProperty("WindowText", _
BindingFlags.Instance Or BindingFlags.NonPublic)
Dim Text As String = _
CType(prop.GetValue(RichTextBox, {}), String).Replace(ControlChars.Cr, "")
If SelectionOnly Then
Dim fi As FieldInfo = _
TypeRTB.GetField("curSelStart", _
BindingFlags.Instance Or BindingFlags.NonPublic)
Dim nCurSelStart As Integer = CType(fi.GetValue(RichTextBox), Integer)
fi = TypeRTB.GetField("curSelEnd", _
BindingFlags.Instance Or BindingFlags.NonPublic)
Dim nCurSelEnd As Integer = _
Math.Min(CType(fi.GetValue(RichTextBox), Integer), Text.Length)
If (nCurSelStart = -1 AndAlso nCurSelEnd = -1) _
OrElse nCurSelStart = nCurSelEnd Then
Text = ""
Else
Text = Text.Substring(nCurSelStart, nCurSelEnd - nCurSelStart)
End If
End If
Return Text
End Function
<System.Runtime.CompilerServices.Extension()> _
Public Function GetTextType(TextBox As TextBoxBase, _
ByVal StartIndex As Integer, ByVal WordLength As Integer) As TypeOfText
Dim TextType As TypeOfText = TypeOfText.Normal
If TypeOf TextBox Is RichTextBox Then
Dim RichTextBox As RichTextBox = DirectCast(TextBox, RichTextBox)
With RichTextBox
Dim CurrentStart As Integer = .SelectionStart, CurrentLength As Integer = .SelectionLength
.Select(StartIndex, WordLength)
If HiddenTextChecker.IsMatch(.SelectedRtf) _
OrElse .SelectionLength < WordLength Then
TextType = TextType Or TypeOfText.Hidden
End If
If .SelectionProtected _
OrElse ProtectedTextChecker.IsMatch(.SelectedRtf) Then
TextType = TextType Or TypeOfText.Protected
End If
.Select(CurrentStart, CurrentLength)
End With
End If
Return TextType
End Function
#End Region
Next, make the following additions and modifications to the file HTMLSpellCheck.vb, within class HTMLSpellCheck:
Private Function CanChangeWord(ByVal StartIndex As Integer, ByVal Length As Integer) As Boolean
If Length = 0 Then
Return False
ElseIf Me.TextBox Is Nothing OrElse TypeOf Me.TextBox Is TextBox Then
Return True
End If
With Me.TextBox
Dim TextType As TypeOfText = .GetTextType(StartIndex, Length)
Select Case True
Case TextType.HasFlag(TypeOfText.Protected)
Return False
Case TextType.HasFlag(TypeOfText.Hidden)
Return SpellCheckHiddenText
Case Else
Return True
End Select
End With
End Function
Private Sub UpdateDocument()
Dim DocumentText As New System.Text.StringBuilder
Dim UpTo = 0
Dim UsesTextBox As Boolean = Me.TextBox IsNot Nothing
For Each item In mc_Words
RemoveHandler item.UpdateClassEvent, AddressOf UpdateClassEvent
RemoveHandler item.SelectionChangedEvent, AddressOf WordSelectionChangedEvent
RemoveHandler item.UpdateWordEvent, AddressOf UpdateWordEvent
Next
mc_Words.Clear()
Dim ScrollPosition As Point
If UsesTextBox Then
Me.TextBox.SetRedrawMode(False)
ScrollPosition = Me.TextBox.GetScrollPosition()
End If
Try
For Each item In _
Dictionary.Formatting.RemoveWordBreaks(mc_Text).Split(" "c)
Dim ThisWordItem = New SpellCheckDialogWords(item, UpTo, CanChangeWord(UpTo, item.Length))
AddHandler ThisWordItem.UpdateClassEvent, AddressOf UpdateClassEvent
AddHandler ThisWordItem.SelectionChangedEvent, AddressOf WordSelectionChangedEvent
AddHandler ThisWordItem.UpdateWordEvent, AddressOf UpdateWordEvent
mc_Words.Add(ThisWordItem)
If ThisWordItem.OrigWord <> "" Then
DocumentText.Append("<a href='" & mc_Words.Count - 1 & "' class='Pending' id='" _
& mc_Words.Count - 1 & "'>" & ThisWordItem.OrigWord & "</a>")
End If
UpTo += item.Length + 1
If UpTo <= mc_Text.Length Then
DocumentText.Append(mc_Text.Substring(UpTo - 1, 1).Replace("&", "&"))
End If
Next item
Finally
If UsesTextBox Then
Me.TextBox.SetScrollPosition(ScrollPosition) : Me.TextBox.SetRedrawMode(True)
End If
End Try
mc_AllowNavigation = True
MyBase.DocumentText = HTMLStyle() & "<BODY onselectstart='return false;'>" & System.Text.RegularExpressions.Regex.Replace(DocumentText.ToString, "\r\n|\n\r|\r|\n", "<BR>")
mc_AllowNavigation = False
End Sub
#End Region
Public CanChangeWord As Boolean
Public Sub New(ByVal OrigWord As String, _
Optional ByVal StartIndex As Integer = 0, _
Optional ByVal CanChangeText As Boolean = True)
Me.OrigWord = OrigWord : mc_NewWord = OrigWord
Me.CanChangeWord = CanChangeText : Me.StartIndex = StartIndex
End Sub
Public OrigWord As String
Dim mc_NewWord As String
Public Property NewWord(Optional ByVal Autoupdate As Boolean = True) As String
Get
Return mc_NewWord
End Get
Set(ByVal value As String)
If Me.CanChangeWord AndAlso value <> mc_NewWord Then
mc_NewWord = value : Me.Changed = True
If Autoupdate Then
UpdateWord()
End If
End If
End Set
End Property
#Region "Constructors"
Public TextBox As TextBoxBase = Nothing
Public SpellCheckHiddenText As Boolean = False
Public Sub New(Optional TextBox As TextBoxBase = Nothing, _
Optional ByVal SpellCheckHiddenText As Boolean = False)
MyBase.AllowWebBrowserDrop = False
MyBase.IsWebBrowserContextMenuEnabled = False
Me.TextBox = TextBox : Me.SpellCheckHiddenText = SpellCheckHiddenText
End Sub
#End Region
#Region "Other Public Subs"
Dim mc_Text As String
Private Settings As New SpellCheckSettings
Public Sub SetText(Optional ByVal Text As String = "", Optional ByVal Settings As SpellCheckSettings = Nothing)
If Settings IsNot Nothing Then Me.Settings = Settings
If String.IsNullOrEmpty(Text) AndAlso Me.TextBox IsNot Nothing Then
mc_Text = Me.TextBox.ExtendedText()
Else
mc_Text = Text
End If
UpdateDocument()
End Sub
Now change the extTextBoxContextMenu_Opening procedure of SpellCheck\Controls\Menu.vb as follows:
Private Sub extTextBoxContextMenu_MenuOpening(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles extTextBoxContextMenu.MenuOpening
If OKToSpellCheck Then
SpellMenuItems.ContextMenuStrip = extTextBoxContextMenu.ContextMenuStrip
If Settings.IgnoreWordOverride(extTextBoxContextMenu.MenuSpellClickReturn.Word) Then
Else
With extTextBoxContextMenu.MenuSpellClickReturn
Beep
parentTextBox.SetRedrawMode(False)
Dim ScrollPosition As Point = parentRichTextBox.GetScrollPosition()
Dim TextType As TypeOfText = parentTextBox.GetTextType(.WordStart, .Word.Length)
If TextType = TypeOfText.Normal Then
SpellMenuItems.AddItems(.Word, CurrentDictionary, CurrentDefinitions, CurrentSynonyms, Settings)
End If
parentRichTextBox.SetScrollPosition(ScrollPosition)
parentTextBox.SetRedrawMode(True)
End With
End If
End If
End Sub
Next, go to the SpellCheckDialog.vb file, and make the following additions and modifications:
Private SourceTextBox As TextBoxBase, SpellCheckHiddenText As Boolean, ShowingSuggestions As Boolean
Private Function EnablingWordChange(Word As HTMLSpellCheck.SpellCheckDialogWords) As Boolean
Return ShowingSuggestions AndAlso Word.CanChangeWord
End Function
Public Overloads Function ShowDialog(ByVal owner As TextBoxBase, _
ByVal SpellCheckControlBase As SpellCheckControlBase, Optional ByVal Text As String = "", _
Optional ByVal SpellCheckHiddenText As Boolean = False) As List(Of HTMLSpellCheck.SpellCheckDialogWords)
Me.SourceTextBox = owner : Me.SpellCheckHiddenText = SpellCheckHiddenText
Me.SpellCheckControlBase = SpellCheckControlBase
If String.IsNullOrEmpty(Text) Then
Text = owner.ExtendedText()
End If
With HtmlSpellCheck1
.TextBox = owner : .SpellCheckHiddenText = SpellCheckHiddenText
.Dictionary = SpellCheckControlBase.CurrentDictionary
.SetText(Text)
End With
pbChangeAll.Maximum = HtmlSpellCheck1.Words.Count - 1
If HtmlSpellCheck1.Words.Count > 0 AndAlso Not EnablingWordChange(HtmlSpellCheck1.Words(0)) Then
btnChange.Enabled = False : btnSkip_Click(btnSkip, EventArgs.Empty)
End If
MyBase.StartPosition = FormStartPosition.CenterParent
MyBase.ShowDialog(owner)
Return HtmlSpellCheck1.Words
End Function
Private Function SelectedWord() As HTMLSpellCheck.SpellCheckDialogWords
Dim sw As HTMLSpellCheck.SpellCheckDialogWords = _
(From xItem In HtmlSpellCheck1.Words Where xItem.Selected).FirstOrDefault
btnChange.Enabled = _
sw IsNot Nothing AndAlso EnablingWordChange(sw)
Return sw
End Function
Private Sub HtmlSpellCheck1_SelectionChanged(ByVal sender As Object, ByVal e As HTMLSpellCheck.HTMLWordEventArgs) _
Handles HtmlSpellCheck1.SelectionChanged
If pnlSuggestions.InvokeRequired Then
Dim HtmlSpellCheck1_SelectionChanged_cb As New HtmlSpellCheck1_SelectionChanged_cb(AddressOf HtmlSpellCheck1_SelectionChanged)
pnlSuggestions.Invoke(HtmlSpellCheck1_SelectionChanged_cb, sender, e)
Else
FillSuggestions()
ShowHideSuggestions(True)
txtChangeTo.Focus()
btnChange.Enabled = _
e.Word IsNot Nothing AndAlso EnablingWordChange(e.Word)
ChangeToUseOldWord = True
txtChangeTo_TextChanged(txtChangeTo, EventArgs.Empty)
ChangeToChanged = False
If e.Word.Selected AndAlso Not btnChange.Enabled Then
MoveToNextWordError()
End If
End If
End Sub
Private Sub ShowHideSuggestions(ByVal Show As Boolean)
ShowingSuggestions = Show
If pnlSuggestions.InvokeRequired Then
Dim ShowHideSuggestions_cb As New ShowHideSuggestions_cb(AddressOf ShowHideSuggestions)
pnlSuggestions.Invoke(ShowHideSuggestions_cb, Show)
Else
Dim theSelectedWord = SelectedWord()
pnlSuggestions.Visible = Show
btnIgnore.Enabled = Show AndAlso theSelectedWord IsNot Nothing AndAlso theSelectedWord.Changed = False AndAlso theSelectedWord.SpellCheckState <> HTMLSpellCheck.SpellCheckDialogWords.SpellCheckStates.OK
btnSkip.Enabled = Show AndAlso (From xItem In HtmlSpellCheck1.Words Where (xItem.SpellCheckState = HTMLSpellCheck.SpellCheckDialogWords.SpellCheckStates.Error OrElse xItem.SpellCheckState = HTMLSpellCheck.SpellCheckDialogWords.SpellCheckStates.Case) AndAlso xItem IsNot theSelectedWord).Count > 0
tstbChangeTo.Enabled = _
MenuCurrentWord IsNot Nothing AndAlso EnablingWordChange(MenuCurrentWord)
btnRevert.Enabled = Show AndAlso theSelectedWord IsNot Nothing AndAlso theSelectedWord.Changed = True
btnChangeAll.Enabled = Not ChangeingAll AndAlso (From xItem In HtmlSpellCheck1.Words Where (xItem.SpellCheckState = HTMLSpellCheck.SpellCheckDialogWords.SpellCheckStates.Case OrElse xItem.SpellCheckState = HTMLSpellCheck.SpellCheckDialogWords.SpellCheckStates.Error)).Count > 0
btnRevertAll.Enabled = (From xItem In HtmlSpellCheck1.Words Where xItem.Changed = True).Count > 0
End If
End Sub
Private Sub txtChangeTo_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles txtChangeTo.KeyUp
Select Case e.KeyCode
Case Keys.Apps
e.Handled = True
If txtChangeTo.ContextMenu Is Nothing Then
txtChangeTo.ContextMenu = New ContextMenu
End If
Dim theSelectedWord = SelectedWord()
If theSelectedWord IsNot Nothing Then
MenuCurrentWord = theSelectedWord
tstbChangeTo.Enabled = _
MenuCurrentWord IsNot Nothing AndAlso EnablingWordChange(MenuCurrentWord)
UpdateMenuItems()
OpenedByClick = False
cmsHTMLSpellCheck.Show(HtmlSpellCheck1, Point.Empty)
End If
End Select
End Sub
Private Sub SpellMenuItems_WordChanged(ByVal sender As Object, ByVal e As Menu.AddSpellItemsToMenu.SpellItemEventArgs) Handles SpellMenuItems.WordChanged
If MenuCurrentWord.CanChangeWord Then
MenuCurrentWord.NewWord = e.Word
MenuCurrentWord.SpellCheckState = HTMLSpellCheck.SpellCheckDialogWords.SpellCheckStates.OK
End If
WordUpdatedFromMenu()
End Sub
Private Sub tstbChangeTo_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles tstbChangeTo.KeyPress
If e.KeyChar = vbCr Then
If MenuCurrentWord.CanChangeWord Then
MenuCurrentWord.NewWord = tstbChangeTo.Text
MenuCurrentWord.SpellCheckState = HTMLSpellCheck.SpellCheckDialogWords.SpellCheckStates.OK
Else
Beep() : MessageBox.Show("This word is protected and/or hidden!")
End If
UpdateMenuItems()
WordUpdatedFromMenu()
End If
End Sub
Private Sub UpdateMenuItems()
If Replace(Dictionary.Formatting.RemoveWordBreaks(MenuCurrentWord.NewWord), " ", "") = MenuCurrentWord.NewWord Then
SpellMenuItems.ContextMenuStrip = cmsHTMLSpellCheck
SpellMenuItems.RemoveSpellMenuItems()
If MenuCurrentWord.CanChangeWord Then
SpellMenuItems.AddItems(MenuCurrentWord.NewWord, SpellCheckControlBase.CurrentDictionary, SpellCheckControlBase.CurrentDefinitions, SpellCheckControlBase.CurrentSynonyms, SpellCheckControlBase.Settings)
End If
End If
mtsChangeTo.Text = "Change " & MenuCurrentWord.NewWord & " to:"
tstbChangeTo.Text = MenuCurrentWord.NewWord
tsiRevertTo.Text = "Revert to " & MenuCurrentWord.OrigWord
tsiRevertTo.Visible = MenuCurrentWord.Changed
cmsHTMLSpellCheck_LocationChanged(cmsHTMLSpellCheck, EventArgs.Empty)
End Sub
Private Sub HtmlSpellCheck1_WordSpellChecked(ByVal sender As Object, ByVal e As HTMLSpellCheck.HTMLWordEventArgs) Handles HtmlSpellCheck1.WordSpellChecked
If pbChangeAll.Visible Then
Dim Progress As Integer = HtmlSpellCheck1.Words.IndexOf(e.Word)
pbChangeAll.SafeInvoke(Function(x As ProgressBar) InlineAssignHelper(x.Value, Progress))
End If
pnlPleaseWait.SafeInvoke(Function(x As Panel) InlineAssignHelper(x.Visible, True))
If e.Word.SpellCheckState = HTMLSpellCheck.SpellCheckDialogWords.SpellCheckStates.Error OrElse e.Word.SpellCheckState = HTMLSpellCheck.SpellCheckDialogWords.SpellCheckStates.Case Then
If ChangeingAll Then
Dim Suggestions = GetSuggestions(e.Word.NewWord)
If Suggestions.Count > 0 AndAlso e.Word.CanChangeWord Then
e.Word.NewWord = Suggestions.First
e.Word.SpellCheckState = HTMLSpellCheck.SpellCheckDialogWords.SpellCheckStates.OK
If SelectedWord() Is e.Word Then
HtmlSpellCheck1_SelectionChanged(HtmlSpellCheck1, New HTMLSpellCheck.HTMLWordEventArgs() With {.Word = e.Word})
End If
End If
Exit Sub
End If
If pnlSuggestions.Visible = False Then
e.Word.Selected = True
End If
ShowHideSuggestions(pnlSuggestions.Visible)
End If
End Sub
Private Function MoveToNextWordError(Optional ByVal DoRecheck As Boolean = True) As Boolean
With HtmlSpellCheck1
MoveToNextWordError = False
Dim StartIndex = 0
Dim theSelectedWord = SelectedWord()
If theSelectedWord IsNot Nothing Then
theSelectedWord.Selected = False
StartIndex = .Words.IndexOf(theSelectedWord) + 1
End If
ReCheck:
For i = StartIndex To .Words.Count - 1
If .Words(i) IsNot Nothing Then
Select Case .Words(i).SpellCheckState
Case HTMLSpellCheck.SpellCheckDialogWords.SpellCheckStates.Error, _
HTMLSpellCheck.SpellCheckDialogWords.SpellCheckStates.Case
If .Words(i).CanChangeWord Then
.Words(i).Selected = True
MoveToNextWordError = True : Exit Function
End If
End Select
If .Words(i).Selected Then
.Words(i).Selected = False
End If
End If
Next
If DoRecheck Then
If StartIndex = 0 Then
CompleteSpellCheck() : Exit Function
End If
StartIndex = 0
GoTo ReCheck
End If
End With
End Function
Private Sub btnChange_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnChange.Click
Dim theSelectedWord = SelectedWord()
If theSelectedWord IsNot Nothing Then
If theSelectedWord.CanChangeWord Then
theSelectedWord.NewWord = txtChangeTo.Text
theSelectedWord.SpellCheckState = HTMLSpellCheck.SpellCheckDialogWords.SpellCheckStates.OK
Else
Beep() : MessageBox.Show("This word is protected and/or hidden!")
End If
End If
btnSkip_Click(btnSkip, EventArgs.Empty)
ShowHideSuggestions(pnlSuggestions.Visible)
End Sub
Private Sub StartChangeAll()
btnAdd.Enabled = False
ChangeingAll = True
If mt_ChangeAll IsNot Nothing AndAlso mt_ChangeAll.IsAlive Then
mt_ChangeAll.Abort()
End If
Dim SelectedWord = Me.SelectedWord
NewTextForChangeAll = txtChangeTo.Text
OldTextForChangeAll = SelectedWord.OrigWord
If SelectedWord IsNot Nothing Then
SelectedWord.Selected = False
End If
ShowHideSuggestions(False)
btnChangeAll.Enabled = False
mt_ChangeAll = New System.Threading.Thread(AddressOf ChangeAll)
mt_ChangeAll.Name = "Spell Check - Change all"
mt_ChangeAll.IsBackground = True
mt_ChangeAll.Start()
End Sub
Private Sub ChangeAll()
Dim WordErrors = _
(From xItem In HtmlSpellCheck1.Words _
Where String.Compare(xItem.OrigWord, OldTextForChangeAll, True) = 0 _
AndAlso (xItem.SpellCheckState = _
HTMLSpellCheck.SpellCheckDialogWords.SpellCheckStates.Case _
OrElse xItem.SpellCheckState = _
HTMLSpellCheck.SpellCheckDialogWords.SpellCheckStates.Error))
For Each item In WordErrors.ToArray
If item.CanChangeWord Then
Dim Suggestions = GetSuggestions(item.NewWord)
If Suggestions.Count > 0 Then
If String.IsNullOrEmpty(NewTextForChangeAll) Then
item.NewWord = Suggestions.First
Else
item.NewWord = NewTextForChangeAll
End If
item.SpellCheckState = HTMLSpellCheck.SpellCheckDialogWords.SpellCheckStates.OK
If SelectedWord() Is item Then
HtmlSpellCheck1_SelectionChanged(HtmlSpellCheck1, _
New HTMLSpellCheck.HTMLWordEventArgs() With {.Word = item})
End If
End If
Else
Beep()
End If
Next
btnRevertAll.SafeInvoke(Function(x As Button) InlineAssignHelper(x.Enabled, True))
If HtmlSpellCheck1.mt_SpellCheck IsNot Nothing _
AndAlso HtmlSpellCheck1.mt_SpellCheck.IsAlive Then
Else
Dim btnChangeAllEnabled = _
(From xItem In HtmlSpellCheck1.Words _
Where (xItem.SpellCheckState = _
HTMLSpellCheck.SpellCheckDialogWords.SpellCheckStates.Case _
OrElse xItem.SpellCheckState = _
HTMLSpellCheck.SpellCheckDialogWords.SpellCheckStates.Error)).Count > 0
ChangeingAll = False
If btnChangeAllEnabled = True Then
btnChangeAll.SafeInvoke(Function(x As Button) _
InlineAssignHelper(x.Enabled, btnChangeAllEnabled))
btnSkip_Click(btnSkip, EventArgs.Empty)
Else
CompleteSpellCheck()
End If
End If
End Sub
Private Sub AddWordButton(ByVal CaseSensitive As Boolean)
Dim theSelectedWord = SelectedWord()
If theSelectedWord IsNot Nothing Then
Dim WordCanBeChanged As Boolean = theSelectedWord.CanChangeWord
Dim Word As String = txtChangeTo.Text
If ChangeToChanged = False Then
Word = theSelectedWord.NewWord
Else
theSelectedWord.NewWord = Word
End If
Try
If SpellCheckControlBase.CurrentDictionary.SpellCheckWord(Word) <> i00SpellCheck.Dictionary.SpellCheckWordError.OK Then
If CaseSensitive = False Then
Word = LCase(Word)
End If
AddWordToDict(Word, theSelectedWord)
End If
Finally
If Not WordCanBeChanged Then
theSelectedWord.NewWord = theSelectedWord.OrigWord
theSelectedWord.Changed = False
End If
End Try
End If
btnSkip_Click(btnSkip, EventArgs.Empty)
End Sub
Private Sub cmsHTMLSpellCheck_Opening(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles cmsHTMLSpellCheck.Opening
If OpenedByClick Then
Dim pCursor = Cursor.Position
Dim pHtml = HtmlSpellCheck1.PointToScreen(New Point(0, 0))
pCursor.X = pCursor.X - pHtml.X
pCursor.Y = pCursor.Y - pHtml.Y
Dim element = HtmlSpellCheck1.Document.GetElementFromPoint(pCursor)
If element IsNot Nothing AndAlso element.Id <> "" Then
Dim ElementNo As Integer
If IsNumeric(Integer.TryParse(element.Id, ElementNo)) AndAlso HtmlSpellCheck1.Words.Count > ElementNo Then
MenuCurrentWord = HtmlSpellCheck1.Words.Item(ElementNo)
tstbChangeTo.Enabled = _
MenuCurrentWord IsNot Nothing AndAlso EnablingWordChange(MenuCurrentWord)
UpdateMenuItems()
Else
e.Cancel = True
End If
Else
e.Cancel = True
End If
Else
OpenedByClick = True
End If
End Sub
Finally, go to file Misc.vb, and change the ShowDialog procedure as follows:
#Region "Show spellcheck dialog"
Public Sub ShowDialog(Optional ByVal SpellCheckHiddenText As Boolean = False) Implements iSpellCheckDialog.ShowDialog
If CurrentDictionary IsNot Nothing AndAlso CurrentDictionary.Loading = False Then
Using SpellCheckDialog As New SpellCheckDialog
Dim SpellCheckResults = _
SpellCheckDialog.ShowDialog(parentTextBox, Me, _
parentTextBox.ExtendedText, SpellCheckHiddenText)
DrawSpellingErrors = False
extTextBoxCommon.LockWindowUpdate(Control.Handle)
Control.SuspendLayout()
Dim SelStart = parentTextBox.SelectionStart
Dim SellLength = parentTextBox.FullSelectionLength
If parentRichTextBox IsNot Nothing Then
Dim Offset As Integer = 0
For Each word In (From xItem In SpellCheckResults Where xItem.Changed = True AndAlso xItem.NewWord <> xItem.OrigWord).ToArray.Reverse
parentRichTextBox.Select(word.StartIndex - Offset, word.OrigWord.Length)
parentRichTextBox.SelectedText = word.NewWord
Next
CType(parentRichTextBox, TextBoxBase).ClearUndo()
Else
Dim OldVertPos = extTextBoxCommon.GetScrollBarLocation(parentTextBox)
Dim NewText As String = parentTextBox.ExtendedText
For Each word In (From xItem In SpellCheckResults Where xItem.Changed = True AndAlso xItem.NewWord <> xItem.OrigWord).ToArray.Reverse
NewText = Strings.Left(NewText, word.StartIndex) & _
word.NewWord & _
Strings.Right(NewText, Len(NewText) - (word.StartIndex + word.OrigWord.Length))
Next
parentTextBox.Text = NewText
extTextBoxCommon.SetScrollBarLocation(parentTextBox, OldVertPos)
End If
parentTextBox.SelectionStart = SelStart
parentTextBox.SelectionLength = SellLength
DrawSpellingErrors = True
Control.ResumeLayout()
extTextBoxCommon.LockWindowUpdate(IntPtr.Zero)
End Using
End If
End Sub
#End Region
Notice that when one invokes ShowDialog(True), the spell-checker spell-checks hidden (invisible) text, but not protected text. If one invokes ShowDialog(False) or simply ShowDialog(), then neither hidden nor protected text is spell-checked.
|