i00 Spell Check and Control Extensions - No Third Party Components Required!

Anyone wishing to use this code in their projects may do so, however are required to leave a post on this page stating that they are using this.
A simple "I am using i00 Spell check in my project" will suffice.

Introduction

I wanted a spell check that I could use in .NET, so like most people would have done, I Googled. After many hours of fruitless searching, I decided to make my own; sure there are plenty of spell checkers out there, but I didn't want one that relied on 3rd party components such as Word or require Internet connectivity to work. Introducing i00 .NET Spell Check, the first and only VB.NET Spell Check written completely in VB! Not only that, it is also open source, and easy to use.

Eventually, this project progressed even further into a generic control extension plugin that provides plugins for text box printing, translation, speech recognition and dictation plus more; while also providing a simple method for users to write their own extensions.

Screenshots

Spell check with definitions

In-menu word definitions and Change to...

Adding words to dictionary

Custom content menus

Crossword generator

Options

Owner draw and RTB support

Spell check dialog

Support for DataGridViews!

Plugin support ... with Label plugin

Plugin support ... with FastColoredTextBox plugin

Implementation

To implement i00 .NET Spell Check into your project, first either:

Add the i00SpellCheck project to your solution and reference it (recommended)

Reference the i00SpellCheck.exe file that is output from this project*

or you can bring all of *.vb files in the "SpellCheck\Spell Check" folder (from the zip) directly into your own project (VB.Net only)*

NOTE: For the methods with the * you will need to also copy the dictionary files to the applications path

Next, simply place this at the very top of your form:

Imports SpellCheck.i00SpellCheck

using i00SpellCheck;

Now you will be able to enable control extensions by going:

Me.EnableControlExtensions()

this.EnableControlExtensions(null);

The above line will enable control extensions on all controls that are supported on the form, and all owned forms that are opened.

Some other examples are below:

'To load a single control extension on a control call:
ControlExtensions.LoadSingleControlExtension(TextBox1, New TextBoxPrinter.TextBoxPrinter)
'To enable spell check on single line textboxes you will need to call:
TextBox1.EnableSpellCheck()
'If you wanted to pass in options you can do so by handling the ControlExtensionAdding event PRIOR to calling EnableControlExtensions:AddHandler ControlExtensions.ControlExtensionAdding, AddressOf ControlExtensionAdding
'Also refer to the commented ControlExtensionAdding Sub in this form for more info'You can also enable spell checking on an individual Control (if supported):
TextBox1.EnableSpellCheck()
'To disable the spell check on a Control:
TextBox1.DisableSpellCheck()
'To see if the spell check is enabled on a Control:Dim SpellCheckEnabled = TextBox1.IsSpellCheckEnabled()
'To see if another control extension is loaded (in this case call see if the TextBoxPrinter Extension is loaded on TextBox1):Dim PrinterExtLoaded = TextBox1.ExtensionCast(Of TextBoxPrinter.TextBoxPrinter)() IsNotNothing'To change spelling options on an individual Control:
TextBox1.SpellCheck.Settings.AllowAdditions = True
TextBox1.SpellCheck.Settings.AllowIgnore = True
TextBox1.SpellCheck.Settings.AllowRemovals = True
TextBox1.SpellCheck.Settings.ShowMistakes = True'etc'To set control extension options / call methods from control extensions (in this case call Print() from TextBox1):Dim PrinterExt = TextBox1.ExtensionCast(Of TextBoxPrinter.TextBoxPrinter)()
PrinterExt.Print()
'To show a spellcheck dialog for an individual Control:Dim iSpellCheckDialog = TryCast(TextBox1.SpellCheck, i00SpellCheck.SpellCheckControlBase.iSpellCheckDialog)
If iSpellCheckDialog IsNotNothingThen
iSpellCheckDialog.ShowDialog()
EndIf'To load a custom dictionary from a saved file:Dim Dictionary = New i00SpellCheck.FlatFileDictionary("c:\Custom.dic")
'To create a new blank dictionary and save it as a fileDim Dictionary = New i00SpellCheck.FlatFileDictionary("c:\Custom.dic", True)
Dictionary.Add("CustomWord1")
Dictionary.Add("CustomWord2")
Dictionary.Add("CustomWord3")
Dictionary.Save()
'To Load a custom dictionary for an individual Control:
TextBox1.SpellCheck.CurrentDictionary = Dictionary
'To Open the dictionary editor for a dictionary associated with a Control:'NOTE: this should only be done after the dictionary has loaded (Control.SpellCheck.CurrentDictionary.Loading = False)
TextBox1.SpellCheck.CurrentDictionary.ShowUIEditor()
'Repaint all of the controls that use the same dictionary...
TextBox1.SpellCheck.InvalidateAllControlsWithSameDict()
''This is used to setup spell check settings when the spell check extension is loaded:PrivateSub ControlExtensionAdding(ByVal sender AsObject, ByVal e As ControlExtensionAddingEventArgs)
Dim SpellCheckControlBase = TryCast(e.Extension, SpellCheckControlBase)
If SpellCheckControlBase IsNotNothingThenStatic SpellCheckSettings As i00SpellCheck.SpellCheckSettings 'Static for settings to be shared amongst all controls, use dim for control specific settings...If SpellCheckSettings IsNothingThen
SpellCheckSettings = New i00SpellCheck.SpellCheckSettings
SpellCheckSettings.AllowAdditions = True'Specifies if you want to allow the user to add words to the dictionary
SpellCheckSettings.AllowIgnore = True'Specifies if you want to allow the user ignore words
SpellCheckSettings.AllowRemovals = True'Specifies if you want to allow users to delete words from the dictionary
SpellCheckSettings.AllowInMenuDefs = True'Specifies if the in menu definitions should be shown for correctly spelled words
SpellCheckSettings.AllowChangeTo = True'Specifies if "Change to..." (to change to a synonym) should be shown in the menu for correctly spelled wordsEndIf
SpellCheckControlBase.Settings = SpellCheckSettings
EndIfEndSub

//To load a single control extension on a control call:
ControlExtensions.LoadSingleControlExtension(TextBox1, New TextBoxPrinter.TextBoxPrinter());
//To enable spell check on single line textboxes you will need to call:
TextBox1.EnableSpellCheck(null);
//If you wanted to pass in options you can do so by handling the ControlExtensionAdding event PRIOR to calling EnableControlExtensions:
ControlExtensions.ControlExtensionAdding += ControlExtensionAdding;
//Also refer to the commented ControlExtensionAdding Sub in this form for more info//You can also enable spell checking on an individual Control (if supported):
TextBox1.EnableSpellCheck(null);
//To disable the spell check on a Control:
TextBox1.DisableSpellCheck();
//To see if the spell check is enabled on a Control:bool SpellCheckEnabled = TextBox1.IsSpellCheckEnabled();
//To see if another control extension is loaded (in this case call see if the TextBoxPrinter Extension is loaded on TextBox1):var PrinterExtLoaded = TextBox1.ExtensionCast<textboxprinter.textboxprinter>() != null;
//To change options on an individual Control:
TextBox1.SpellCheck(true, null).Settings.AllowAdditions = true;
TextBox1.SpellCheck(true, null).Settings.AllowIgnore = true;
TextBox1.SpellCheck(true, null).Settings.AllowRemovals = true;
TextBox1.SpellCheck(true, null).Settings.ShowMistakes = true;
//etc//To set control extension options / call methods from control extensions (in this case call Print() from TextBox1):object PrinterExt = TextBox1.ExtensionCast<textboxprinter.textboxprinter>();
PrinterExt.Print();
//To show a spellcheck dialog for an individual Control:var iSpellCheckDialog = TextBox1.SpellCheck(true,null) as i00SpellCheck.SpellCheckControlBase.iSpellCheckDialog;
if (iSpellCheckDialog != null) {
iSpellCheckDialog.ShowDialog();
}
//To load a custom dictionary from a saved file:
i00SpellCheck.FlatFileDictionary Dictionary = new i00SpellCheck.FlatFileDictionary("c:\\Custom.dic", false);
//To create a new blank dictionary and save it as a file
i00SpellCheck.FlatFileDictionary Dictionary = new i00SpellCheck.FlatFileDictionary("c:\\Custom.dic", true);
Dictionary.Add("CustomWord1");
Dictionary.Add("CustomWord2");
Dictionary.Add("CustomWord3");
Dictionary.Save(Dictionary.Filename, true);
//To Load a custom dictionary for an individual Control:
TextBox1.SpellCheck(true, null).CurrentDictionary = Dictionary;
//To Open the dictionary editor for a dictionary associated with a Control://NOTE: this should only be done after the dictionary has loaded (Control.SpellCheck.CurrentDictionary.Loading = False)
TextBox1.SpellCheck(true, null).CurrentDictionary.ShowUIEditor();
//Repaint all of the controls that use the same dictionary...
TextBox1.SpellCheck(true, null).InvalidateAllControlsWithSameDict(true);
//This is used to setup spell check settings when the spell check extension is loaded:static i00SpellCheck.SpellCheckSettings SpellCheckSettings = null;//Static for settings to be shared amongst all controls, use "i00SpellCheck.SpellCheckSettings SpellCheckSettings = null;" in the method below for control specific settings...privatevoid ControlExtensionAdding(object sender, i00SpellCheck.MiscControlExtension.ControlExtensionAddingEventArgs e)
{
var SpellCheckControlBase = e.Extension as SpellCheckControlBase;
if (SpellCheckControlBase != null)
{
//i00SpellCheck.SpellCheckSettings SpellCheckSettings = null;if (SpellCheckSettings == null)
{
SpellCheckSettings = new i00SpellCheck.SpellCheckSettings();
SpellCheckSettings.AllowAdditions = true; //Specifies if you want to allow the user to add words to the dictionary
SpellCheckSettings.AllowIgnore = true; //Specifies if you want to allow the user ignore words
SpellCheckSettings.AllowRemovals = true; //Specifies if you want to allow users to delete words from the dictionary
SpellCheckSettings.AllowInMenuDefs = true; //Specifies if the in menu definitions should be shown for correctly spelled words
SpellCheckSettings.AllowChangeTo = true; //Specifies if "Change to..." (to change to a synonym) should be shown in the menu for correctly spelled words
}
SpellCheckControlBase.Settings = SpellCheckSettings;
}
}</textboxprinter.textboxprinter></textboxprinter.textboxprinter>

Even more examples are included in the Test project in the download.

Plugins

Since version 20120618 i00SpellCheck has plugin support.

Plugins in i00SpellCheck allow components to be spell checked by making a dll or exe file that contains a public class that inherits i00SpellCheck.SpellCheckControlBase.

They automatically get picked up and allow the spellchecking of extra controls, with no reference to the file itself required. However you will need to place them in the applications path.

The use of plugins allow users to enable spellchecking of their controls, without having to change the i00SpellCheck project.

Another use for them could be to allow the programmer to quickly see if they have spelling errors on forms etc. For example placing the LabelPlugin.exe file in an application path (that already uses i00SpellCheck) will cause all labels in the existing project to be spell checked ... with NO code changes! When the developer wants to deploy their application they simply need to remove the LabelPlugin.exe file, and labels will no longer be corrected.

The basic procedures for creating a plugin are as follows:

Start by creating a new project (class library or exe)

Reference i00SpellCheck

Make a class that inherits i00SpellCheck.SpellCheckControlBase

Override the ControlType Property to return the type of control that you want your plugin to spell check

Add your code

For examples on inheriting i00SpellCheck.SpellCheckControlBase check out the examples in the Plugins path in the download.

Projects

The included projects and a brief description of each are as follows:

i00SpellCheck - Contains the classes for the spellcheck core / TextBox and DataGridView plugins plus the core components required for other plugins to work

Plugins\LabelPlugin - Contains a plugin that checks the spelling of Labels

Plugins\OSControlRenderer - Contains aplugin that renders the TreeView and ListViews to the same that they appear in Windows

Plugins\SelectedControlHighlight - Contains a plugin that extends a variety of Controls so that they appear to have a "glow" when selected

Plugins\TextBoxPrinter - Contains a plugin that extends TextBoxBase to support printing

Plugins\TextBoxSpeechRecognition - Contains a plugin that extends TextBoxBase to include support for voice input (double tap F12) and dictation

Plugins\TextBoxTranslator - Contains a plugin that extends TextBoxBase to support Google Translation

Tests\CSharpTest - A test project demonstrating the use of i00 Spell Check in C#

*Tests\Test - A test project that contains advanced implementation of i00 SpellCheck and control extensions

Tests\3rd Party Dictionaries\HanksDictionaryTest - A test project that demonstrates the use of 3rd party spelling engines in i00 Spell Check. Hank's dictionary in this case (by tewuapple (Hank))

Tests\3rd Party Dictionaries\OpenOfficeHunspellDictionaryTest - A test project that demonstrates the use of 3rd party spelling engines in i00 Spell Check. Hunspell in this case which has support for open office dictionaries

Tests\3rd Party Dictionaries\WordDictionaryTest - A test project that demonstrates the use of 3rd party spelling engines in i00 Spell Check. Microsoft Word in this case

* = default startup project

Points of Interest

The words that get checked are added to a dictionary cache to speed up checking - the smaller cache is checked first. If the word is not found in the cache, then it checks the main dictionary.

I use fields (public variables) instead of properties for some basic classes, as they are about 2x faster than properties.

Downloads

Total Downloads:

Downloads per day:

Change Log

(Bold items are things that end users will notice)

20140111

i00SpellCheck

Fixed single line textbox issue where EnableSpellCheck would be required to be needed 2x (found by hoodch)

Updated the plugin manager to the latest ... now supports paths and shadow copying (this is not implemented in this project)

Added help button to spell check dialog (for people who don't know about holding F1)

Test

Made enabled button work for each tab on demo form

TextBoxSpeechRecognition

Fixed a few issues with the dictation where it would not put in the dictated text

Fixed a rare occuring bug where an error would be thrown with the spellcheck cache

User dictionary file is now separate from the built in dictionary

Ignored words are now stored in the user dictionary

Updated the FlatFile dictionary editor to support the new user dictionary

Added i00Binding List to the project for the FlatFile Dictionary editor... you can remove the reference, if you want, but will first have to remove the dictionary editor if you don't require it (found in i00SpellCheck\Spell Check\Engine\Dictionary\Flat File\Editor)

Changed the dictionary dramatically to support custom classes to enable the checking of other dictionary formats

20120625

Changed the way the words get added to the dictionary cache (increased spell checking speed)

Improved the speed of the FastColoredTextBox Plugin

Made the test project automatically pickup any plugins in the project path and add them to tabs automatically - the references to the plugins are not required, they were added for the LabelPlugin and FastColoredTextBoxPlugin so that they automatically get placed in the same folder when the project is built!

20120622 - FastColoredTextBox

Changed some internal workings of the spell checker

Added support for FastColoredTextBox with included plugin!

20120618 - Plugins!

Added test plugin to project that grants the ability to spell check labels

Changed the structure / inner workings of the spell check alot / made the spell check more modular and plugins possible!

Fixed a bug where the settings were not being applied under certain circumstances to spell check controls

Grid view spell checking now is shown on cells even when their not being edited

20120609 - DataGridView's are go!

Added support for DataGridViews (requested by in2tech)

Fixed a bug where the underlines would not draw in the correct positions when word wrapping is disabled

Fixed a bug where single line TextBoxes would not always show spelling errors

20120608 - Disabling and bug fixes

Fixed a bug where if you had an apostrophe at the start of a word it would push the underline spacing out (found by jwinney)

Added ability to disable the spell check on a TextBox (requested by Gabriel X)

Fixed a bug where the standard TextBox was not refreshing properly since the new rendering method was added

Fixed bug where if a TextBox contained errors and all text was deleted the underlines would still show (found by jim400)

Some minor interface changes with splash screen and "alt" for menu

20120203

Tooltips now have image support and images for some definitions

Fixed tool tip rendering issues

You can now press F3 to change case of the selected text (requested by rykk)

Made "-" be classified as a word break char

Fixed an error that would re-paint the textbox errors 2x

Disabled Cut/Copy/Paste options in menu if not on an STA thread as this would error

20120102 - Happy New Year!

Modified definitions to lookup from file dynamically rather than being loaded into memory to reduce RAM usage ~56MB saved!

Changed settings so that all the spellcheck settings are in a single class

Cleaned up the SpellCheckTextBox class and subclasses to make settings easily editable with a property grid

Added property grid to the test project

Added a dictionary editor

Added a "bare-bones" test project to the solution, to make it simpler for users to see how easy it can be to use i00 .NET Spell Check in your projects!

Changed the render method to eliminate redraw flicker, added a setting to revert to the old render method "RenderCompatibility"

20111202 - Now with dialog!

Cleaned up some stuff ... moved HTML formatted tooltip + HTML ToolStripItem into their own controls

Made the Text ToolStripSeperator look and function better

Made the right click menu items portable so that they can be added to any menu for other things - not so tightly bound to the text box

Implementing a spell check dialog for F7 style spell checking (select text box and press F7!... can also be called with: TextBoxName.SpellCheck.ShowDialog())

20111109 - In-menu definitions, synonyms and fixes!

Changed tooltip definitions to match more words from their word base, e.g. "suggestions" matches "suggestion" for definition since no definition is matched explicitly for suggestions and states that it is plural in the tip

Tooltip for definitions is now owner draw so that it appears a little nicer

Fixed a case matching bug where "This" would suggest "this" rather than "This" (requested by TxDeadhead)

Words like "Chris's" now suggest "Chris'" instead of "Chris's"

Words that end in an ' no longer appear as being misspelled

Made the context menu position itself a little better if near the bottom or right sides of a screen

Fixed a bug where, if you press the context menu button on the keyboard multiple times, the menu would add multiple of the same corrections to the context menu

Sped up loading of dictionary file

Fixed a bug in the definition file - all adjectives and adverbs were mixed up (i.e., all adjectives were listed as adverbs, and all adverbs were listed as adjectives)!

Various speed optimizations in finding word suggestions, to lookup misspelled word "suggestions" used to take ~250ms, now down to ~150ms

Words with interesting cases (such as SUpport, SupporT etc) now get picked up (requested by TxDeadhead)

Now doesn't fall over if the dictionary, definitions or synonyms files have been removed - just removes functionality for that bit

Added synonyms; "Change to..." menu item (requested by NtEditor)

20111106 - Been busy!

Various speed optimizations

Dictionary is now stored as a Flat File for portability

Added owner draw support for spelling errors

Added the ability to customize colors for highlighting misspelled words

Added some examples of how to customize the appearance of the spell check

Word definitions added for spelling suggestions ... so if you are unsure of the correct spelling out of the suggestions, you can pick the correct one from the definition

The right click menu in .NET comes up from the middle of a text box when pressing the context menu button on the keyboard - It has now been modified to pop-out from the carets location

Cross word generator - plan to make solver later too!

Support added for Rich Text Boxes

Added Suggestion Lookup Example

20111011 - Some fun extras

Added anagram lookup

Added Scrabble helper

20111008 - Minor changes

Fixed a bug where the text box underlines would not always draw initially until the textbox was scrolled or had some text changed

Cleaned up the interface to made it look more professional

20111006

Initial Release

Possible Issues

SpellCheckTextBox

Since the Textbox has no way to really draw on it "nicely", I used to capture the WM_PAINT of the control and then draw on the textbox graphics that was set by going Graphics.FromHwnd... this seemed to work well but produced a slight flicker that I thought was undesirable...

As of version 20120102, the render method now uses layered windows (by default), this basically means that all of the underlines that appear to be drawn on the control are actually drawn on another window over the top of the control ...

So how does this affect the user? Well in most cases it doesn't, the form is click-through and only the drawings are visible not the form itself. In fact if you press start + tab in Windows Vista / 7 to activate Flip3D, it even appears on the same window!

As I said above "in most cases"...

MIDI forms I haven't tested, but am quite sure that they won't work using the new render method.

With overlapping textbooks the text corrections on the underneath control "float"over the control that is on top, and if the textbox is off the form, the corrections "float" off the form!

So in cases such as the above, you will have to go back to the older "compatible" rending, this can be done in these cases by going:

Thanks

A special thanks to Pavel Torgashov for his excellent FastColoredTextBox control. This control is used in the solution to test i00SpellCheck's plugin architecture with 3rd party controls. i00 has not modified this control in any way and is only responsible for integrating the spell checking ability to it via an i00SpellCheck plugin. In no way is this control required for spell checking functions in other projects within the solution.

i want to say a very big thank you for saving my life, thank you very very much..... i cant express how grateful i am, thank you. i had search and search for days for a spell checker code but was fruitless until i came across i00 spell checker, its such a great work you've done, you are great thanks alot.

An observation that i don't quite understand yet enough to fix.
The data in my datagridview is derived from a 3rd party application that outputs the majority of strings in upper case.

When there is a spelling mistake, or a word that isnt know, the undersquigle (is that a word ) is displayed under the respective word/s. When i select the cell the undersquigle remains shown. When i open/edit the cell the undersquigle is not longer visible and therefore i cant right click to correct the error.

If i duplicate the text in lower case (in same or another cell) the undersquigle is shown properly and i can right click and select from the options to correct the word.

If i change just one letter to lower case, leaving the rest as uper case, then i can also right click and select from the options to correct the word.

I have the ingore word in upper case set to false for the datagridview control

Thanks. With some break points and lots of F8 steps i was abot to confirm that the text box parent is the DGV. So not sure if need to do anymore in terms of copying settings but will wait your next version release.

Have spent many hours attempting to debug and step through through your code, but not able to identify the right section that shows the text (my text that needs to be editted) in the text box (rather than DGV). Can you point me in the right direction?