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.
- 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.
- 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.)
- Add libhunspell.vcproj to your solution.
- 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
- Copy the HSpell*.c and HSpell*.h files into your project's directory, and add them to your project.
- Make your project depend on libhunspell.
- 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
- Copy the directory HSpellEdit into a convienent place within your project, and add HSpellEdit_dll.vcproj to your solution.
- Make your project depend on HSpellEdit_dll. (HSpellEdit_dll needs to depend on libhunspell.)
- Add the processor define HSPELLEDIT_DLL to both the Release and Debug builds of your project.
Part 3: Using CHSpellEdit in your Application
- 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. - Call
CHSpellEdit::Initialize(this)
in the InitInstance
member of your CWinApp
descendant after calling CWinApp::SetRegistryKey()
. - 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.) - 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.) - 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
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.
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:
- The directory specified in the registry.
- The executable directory. *
- The dic subdirectory of the executable directory. *
- The
CSIDL_COMMON_APPDATA
directory *
[This directory is checked only if running on Windows ME or Windows 2000 or better.] - The
CSIDL_APPDATA
directory - The OpenOffice.org dictionary location. *
- 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:
- The directory specified in the registry.
- C:\Program Files\HSpellEditTest\
- C:\Program Files\HSpellEditTest\dic\
- C:\Documents and Settings\All Users\Application Data\
- C:\Documents and Settings\Curtis\Application Data\
- C:\Program Files\OpenOffice.org 2.3\share\dict\ooo\
- 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.
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
- 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