Click here to Skip to main content
15,881,204 members
Articles / Programming Languages / C++
Article

Spell Checking Edit Control (Using HunSpell)

Rate me:
Please Sign up or sign in to vote.
4.53/5 (9 votes)
20 Nov 2007Public Domain7 min read 63K   2.7K   28   16
A CEdit control with an up-to-date, internationalizable spell checker.

Screenshot - CHSpellEdit-1.gif

Screenshot - CHSpellEdit-2.gif

Introduction

I was inspired to write this control after looking at both Matthew Gullett's spell checking engine and Steve King's CSpellEdit control.

I liked CSpellEdit's simplicity, but the integration with the CEdit control felt a little better in CFPSSpellingEditCtrl, so I combined the two, updated the spell checking engine used to Hunspell instead of MySpell, added user dictionary code, and generalized it as much as possible.

Usage

To use this edit box, there are three steps:

  • Adding Hunspell to your solution
  • Adding CHSpellEdit to your solution (as a DLL) or project (as static code)
  • Using CHSpellEdit in your application.

Part 1: Adding Hunspell to your Solution

To satisfy the LGPL, these directions build hunspell as a DLL, just to be safe.

  1. Get an up-to-date version of the Hunspell source code from SourceForge. Extract it to a convienent directory. Copy the src\hunspell directory into a convienent place within your solution, and copy the src\win_api directory into the same place. (The two directories need to be at the same level.)

    You'll also need to get a dictionary from the same site (unless Mozilla Firefox or OpenOffice.org is already installed on your machine, and even then, you may wish to provide a dictionary with your program) and put the en_US.dic and en_US.aff (or the equivalent files for the language you chose) in one of the directories mentioned below. Note that Hunspell can use MySpell-compatible dictionaries.

  2. Apply hunspell-1.2.1-dllbuild.patch. Apply either hunspell-1.2.1-vc70.patch or hunspell-1.2.1-vc71.patch if required.

    (Steps 1 and 2 only need to be done if you choose to get updated source for Hunspell. If you choose not to, then copy the hunspell and win_api directories from the demo project into a convienent place in your solution.)

  3. Add libhunspell.vcproj to your solution.

  4. Make your Debug build use the Debug_dll build of Hunspell, and the Release build use the Release_dll build of Hunspell.
    [Use Build > Configuration Manager in Visual Studio .NET 2003 to do this.]

Choose either 2a or 2b at this point for the next 3 steps.

Adding CHSpellEdit to your solution (as a DLL) or Project (As Static Code)

Part 2a: Adding CHSpellEdit in your Project as Static Code

  1. Copy the HSpell*.c and HSpell*.h files into your project's directory, and add them to your project.
  2. Make your project depend on libhunspell.
  3. Edit your stdafx.h to make sure it defines WINVER, _WIN32_WINNT, and _WIN32_IE as 0x0500, and _WIN32_WINDOWS as 0x0410, at a minimum.

    If you do not do this step, HSpellEdit.h will stop with a C1189 error. (it hits a #error line.) This is to prevent other compilation errors later.
    The code takes advantage of capabilities of Windows 98, Windows 2000, and/or Windows ME when they are available, but does not *require* them. However, these define needs to be set in order to use these capabilities at all.

Part 2b: Adding the CHSpellEdit DLL to your Solution

  1. Copy the directory HSpellEdit into a convienent place within your project, and add HSpellEdit_dll.vcproj to your solution.
  2. Make your project depend on HSpellEdit_dll. (HSpellEdit_dll needs to depend on libhunspell.)
  3. Add the processor define HSPELLEDIT_DLL to both the Release and Debug builds of your project.

Part 3: Using CHSpellEdit in your Application

  1. Add #include "HSpellEdit.h" to the .cpp file that contains your CWinApp descendant's InitInstance (and ExitInstance) routines, and in any .h files that define dialog box classes that will use CHSpellEdit.
  2. Call CHSpellEdit::Initialize(this) in the InitInstance member of your CWinApp descendant after calling CWinApp::SetRegistryKey().
  3. Call CHSpellEdit::Terminate() in the ExitInstance member of your CWinApp descendant. (In a dialog box application, you can call it in InitInstance after DoModal has been called, but before InitInstance exits.)
  4. Define a CHSpellEdit variable, and attach it to your edit box. (In your DoDataExchange routine, there should be a DDX_Control call referring to your edit box ID and your CHSpellEdit variable. If there was already a CEdit variable, just change it to a CHSpellEdit variable.)
  5. Credit the appropriate people in your About box or equivalent. (I don't ask for credit, but it would be nice. My changes are under the license below. Matthew Gullett does ask for credit, however, so to satisfy all legalities, you probably need to credit him.)
/* LICENSE:
 * This code is absolutely free to use and modify. The code is provided 
 * "as is" with no expressed or implied warranty. The author accepts no 
 * liability if it causes any damage to your computer, causes your pet to
 * fall ill, increases baldness or makes your car start emitting strange
 * noises when you start it up.
 * This code has no bugs, just undocumented features!
 */

Requirements for Your Users

The only requirement that HSpellEdit actually places on your users is that if they run Windows 95 or Windows NT 4.0, that they also have an updated version (better than 4.71) of SHFolder.dll installed. The URL to get the US English version is in the comments at the appropriate point in the code. HSpellEdit.cpp detects the Windows version of the user and degrades accordingly. No code that requires Windows 98, Me, or 2000 is relied upon, but code that uses the capabilities of Windows 98, Me, or 2000 is used when these operating systems are available.

You'll want to create IDS_HSPELLEDIT_SHFOLDER_ERROR in your string table to define the message to use if the check for SHFolder.dll fails. If there is none, a default message will be used.

Usage Notes

  1. If you use the DLL, please make sure that you use the same number for any IDS_HSPELLEDIT_* string that the DLL uses. The DLL provides strings in US English, but the strings can be overridden or translated by your application. You may wish to specify a string table in another language for translated strings, and I'd appreciate the translations being sent to me.

  2. Three preprocessor definitions affect finding the dictionary files:

    The preprocessor definition HSPELLEDIT_NO_REGISTRY_CHECK turns off loading and saving the path information to the registry.

    The preprocessor definition HSPELLEDIT_NO_EXTERNAL_PROGRAMS_CHECK turns off loading the path information from the registry entries for OpenOffice.org 2.3, 2.2, 2.0, or Mozilla Firefox 2.0.0.0 or greater. (They are tried in that order.)

    The preprocessor definition HSPELLEDIT_NO_SELFREF_CHECK turns off checking the executable directory (and the "dic" subdirectory of the same) for the dictionary files.

    Here are the order the directories are checked:

    1. The directory specified in the registry.
    2. The executable directory. *
    3. The dic subdirectory of the executable directory. *
    4. The CSIDL_COMMON_APPDATA directory *
      [This directory is checked only if running on Windows ME or Windows 2000 or better.]
    5. The CSIDL_APPDATA directory
    6. The OpenOffice.org dictionary location. *
    7. The Mozilla Firefox dictionary location. *

    Locations marked with * are not used to find the user dictionary, which will be written to CSIDL_APPDATA if it does not exist.

    If no regular dictionaries exist, no spell checking will happen, but your program will otherwise work.

    The directories that will be searched in if: A) Program is in C:\Program Files\HSpellEditTest
    B) Username is "Curtis", running on a US English version of Windows XP
    C) OpenOffice 2.3 and Mozilla Firefox 2.0 are installed
    are these:

    1. The directory specified in the registry.
    2. C:\Program Files\HSpellEditTest\
    3. C:\Program Files\HSpellEditTest\dic\
    4. C:\Documents and Settings\All Users\Application Data\
    5. C:\Documents and Settings\Curtis\Application Data\
    6. C:\Program Files\OpenOffice.org 2.3\share\dict\ooo\
    7. C:\Program Files\Mozilla Firefox\dictionaries\

    Both a .dic and .aff file are required for your language in one of these directories to be a usable dictionary for HSpellEdit.

    If your language is not available in a particular directory, HSpellEdit will check for other sublanguages of your language in descending order, (Windows specifies the order, HSpellEdit does not) then defaults to US English (en_US) before going on to the next directory.

    Once a dictionary is found, its location is saved to the registry, unless HSPELLEDIT_NO_REGISTRY_CHECK was defined.

    If you are writing an installer for a program using HSpellEdit, it is probably best to put your dictionaries in locations 4 and 5, rather than locations 2 or 3.

  3. To internationalize the menus, put these constants in the string table:

    IDS_HSPELLEDIT_SUGGESTIONS
    IDS_HSPELLEDIT_NO_SUGGESTIONS
    IDS_HSPELLEDIT_ADD
    IDS_HSPELLEDIT_IGNORE

    You only need to add these constants to your string table if MFC does not already define them for your language. (They will be in MFC71xxx.dll, where xxx is a 3-letter language code, and in the MFC source at atlmfc\src\mfc\l.xxx\prompts.rc if MFC DOES define them for your language.)

    ID_EDIT_CUT
    ID_EDIT_COPY
    ID_EDIT_PASTE
    ID_EDIT_SELECT_ALL
    ID_EDIT_UNDO
  4. The HShellEdit DLL exports the same DllGetVersion call that shell32.dll, shlwapi.dll, comctl32.dll, and shfolder.dll does, so you can get the version of the DLL in the same way.

Points of Interest

I tried to allow for use in "least-priviledge-required" situations, which is why CSIDL_APPDATA (which should be writable except in extremely limited circumstances) is used as one place to store the dictionaries.

History

  • Version 0.90
    Initial Release

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionMemory violation Pin
redataliani5-Nov-19 3:56
redataliani5-Nov-19 3:56 
QuestionVisual Studio 6 Pin
andwan024-Aug-12 4:36
andwan024-Aug-12 4:36 
AnswerRe: Visual Studio 6 Pin
evegnibmw18-Sep-12 23:38
evegnibmw18-Sep-12 23:38 
QuestionUsing Control without C++ Pin
Member 465036528-Jul-12 4:29
Member 465036528-Jul-12 4:29 
GeneralDoesn't work for CRichEditCtrl... Pin
sachin_kl@yahoo.com20-Dec-10 22:07
sachin_kl@yahoo.com20-Dec-10 22:07 
GeneralResource Leak Pin
LeslieM18-Aug-10 20:35
LeslieM18-Aug-10 20:35 
GeneralGetting error in DoModal() when using CHSpellEdit - CHandleMap NULL Pin
Sanil Talathi29-Jun-10 5:10
Sanil Talathi29-Jun-10 5:10 
GeneralRe: Getting error in DoModal() when using CHSpellEdit - CHandleMap NULL Pin
Sanil Talathi6-Jul-10 4:43
Sanil Talathi6-Jul-10 4:43 
Generalusing in .net Pin
AhmedSuria25-Aug-08 23:51
AhmedSuria25-Aug-08 23:51 
GeneralRe: using in .net Pin
Curtis J1-Oct-08 14:08
Curtis J1-Oct-08 14:08 
NewsNHunspell = Hunspell for .NET Pin
Thomas Maierhofer (Tom)21-Feb-09 23:32
Thomas Maierhofer (Tom)21-Feb-09 23:32 
GeneralGreat job Pin
Trapper300125-Aug-08 9:40
Trapper300125-Aug-08 9:40 
GeneralI like it Pin
code_discuss27-Nov-07 15:31
code_discuss27-Nov-07 15:31 
AnswerRe: I like it Pin
Curtis J23-Dec-07 17:45
Curtis J23-Dec-07 17:45 
QuestionWhat happened to Spellican? Pin
matt200020-Nov-07 14:21
matt200020-Nov-07 14:21 
AnswerRe: What happened to Spellican? Pin
Curtis J20-Nov-07 16:52
Curtis J20-Nov-07 16:52 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.