Help Your Application Users Become Great Spellers

Virtually all interactive applications nowadays involve the input of human-readable text. From accounting to instant messaging, we all want to look professional and use communication that speaks to our point and not to our ham-fisted typos. Sure, you can always use a dictionary attack on human-readable strings, but to really help the user you should offer the familiar "suggestions" interactions provided by your typical office word processor.

Fortunately, a variety of spell checking products are available for the Visual C++ and Visual Basic developer. This article looks at SpellChecker, an easy-to-use shareware DLL add-on by GPP Software.

A Speller Without a Lot of Baggage

SpellChecker is a self-contained Windows Dynamic Link Library (DLL) that has all of its functionality in SPLCHK32.DLL. The included setup script installs it in your System32 directory. By using the provided import library or Win32 LoadLibrary() calls, you can obtain a spell checking functionality that normally requires the use of DDE/OLE communications with products such as Microsoft Word. Thus, it should be simple to integrate it into any development environment that can call DLL functions.

SpellChecker dictionaries can reside in flat files, Microsoft Access, or Microsoft SQL Server databases to enable sharing across a network. SpellChecker comes with a standard UK English dictionary of 113,000 words, but you easily can build up your own dictionaries—even for different languages. (Free dictionaries for other languages can be obtained around the Internet or from GNU Aspell project, for example.) You need only pass SpellChecker edit fields or files containing many words.

SpellChecker provides essential API calls to spell check the following:

  • Windows Edit fields
  • String buffers
  • ASCII files
  • Individual words

SpellChecker is available in a 30-day evaluation version. During the evaluation period, a dialog periodically pops up reminding you to register. At the end of the evaluation period, you can pay the $99 registration fee.

"Hello SpellChecker"

Without further ado, take a look at how quickly you can perform the simplest of spelling functions: checking and correcting an arbitrary buffer. Using the supplied "demo" project, I compiled the basic MFC app shown in Figure 1 with Visual Studio.

Figure 1: Spell Check an Arbitrary Buffer

The upper-left window is an ordinary MFC dialog created in the sample app. The lower-right dialog was invoked by SpellChecker as a result of the API calls. The buttons work in the expected ways:

  • Ignore: Ignores current word
  • Ignore All: Ignores current and all future occurrences in this session
  • Replace: Replaces current word with "Change To" selection (does not affect dictionaries)
  • Suggest: Updates suggestions based on current value of "Change To" (user typed over, presumably)
  • Add: Adds the word to the dictionary (The dictionary is not case-sensitive, but it will remember the case entered by the user next time.)
  • Add+Replace: Does an Add followed by Replace in one step
  • Undo Add: Undoes the last Add from this session (cannot affect prior sessions)

Now, take a look at the code used to build this particular demo, starting from the MFC "OK" button handler:

#include "splchk1.h"    // SpellChecker API
#include "sizes.h"      // SpellChecker Size Defs

void CBufferDlg::OnOK() {

   int ilRc;
   char szlString[1025];

   UpdateData(TRUE);
   lstrcpy((LPSTR)szlString, (LPCSTR)tmBuffer);
   ilRc = SpellLoadDictionary();
   if(!ilRc) ilRc = SpellCheckBuffer(this->GetSafeHwnd(),
                                     (LPSTR)szlString, 1024);
   lstrcpy((LPSTR)tmBuffer,(LPSTR)szlString);
   UpdateData(FALSE);
   SpellCheckError(this->GetSafeHwnd(), ilRc);
   SpellUnloadDictionary();

The code is about as simple as anyone could ask for! It has tmBuffer linked to the contents of the edit buffer and copied in by the UpdateData(TRUE). Then, it calls SpellLoadDictionary(), which is an all-in-one initialization function. Coincidentally, if the product is unregistered, this is when the registration reminder pops up. Then, it's basically a matter of kicking off the spell check routine by calling SpellCheckBuffer() with the current hWnd, a copy of your buffer, and maximum length. Remember, a spelling correction session can arbitrarily change the length of the string needed.

After the user has completed the interactive session, the code returns back from SpellCheckBuffer(), copies the new string for storage, and displays any error conditions that might have resulted from the session. The most likely error would be a missing dictionary or similar problem, I suppose.

Because the example was designed to be completely self-contained, the code frees all the resources at the end with a call to SpellUnloadDictionary().

Spell Checking a Live Edit Field

One of the coolest SpellChecker features is the ability to spell check a live edit field in place. The following is an example of the code for that:

void CMainFrame::OnToolsSpellEdit() {

   int ilRc;
   ilRc = SpellLoadDictionary();
   if(!ilRc) ilRc = SpellCheckEdit(this->GetSafeHwnd(),
                                   tmEdit.m_hWnd);
   SpellCheckError(this->GetSafeHwnd(), ilRc);
   SpellUnloadDictionary();

This time, the code calls SpellCheckEdit() instead of SpellCheckBuffer and passes in both the parent hWnd and the edit control's hWnd, which should be enough to get the job done. No need to repeat the screen dump for this one.

Expand Your Vocabulary

Importing words is as easy as pie with SpellChecker. Basically, you do the usual setup and then call SpellImportWords() with the name of an ASCII file containing the new words to add:

void CMainFrame::OnToolsSpellImport() {

   int ilRc;
   char szlTFileName[MAXFILENAMELEN + 1],
        szlTQualName[MAXFILENAMELEN + 1];

   if(FileDlg(this, FD_OPEN, "Import",
              "Text Files (*.TXT)|*.TXT|All Files (*.*)|*.*||",
              "TXT", OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST,
              szlTFileName, szlTQualName, 0)) {
      // User has selected a text file to be imported
      ilRc = SpellLoadDictionary();
      if(!ilRc) ilRc = SpellImportWords(szlTQualName);

      if(!ilRc) {
         AfxMessageBox("Import completed successfully");
      } else {
         SpellCheckError(this->GetSafeHwnd(), ilRc);
      }

      SpellUnloadDictionary();
   }
}

I was impressed to find that it actually updated the permanent dictionary file ("UK.DIC") after this API call rather than writing a temporary file. Upon inspection, the dictionary had grown an appropriate amount and its datestamp had changed, of course. As you can see in Figure 2, the word "Codeguru" was added to the dictionary. So, it appears as a possible suggestion.

Figure 2: SpellChecker Recognizes Codeguru as a Valid Word

As far as I can tell, suggestions are always listed alphabetically, not probabilistically. So, even if a word is off by only one letter, the user might need to scroll. Maybe SpellChecker can offer that as an option in a future release.

Other Spell Checker DLLs

Of course, different developers have different requirement levels for their spell check needs. I encourage you to check out several APIs before committing yourself to any. Here are a couple of others to browse:

  • Wintertree Software's Sentry Spelling Checker Engine works with RichEdit type controls and offers an "as you type" mode as well. Other products include Java and HTML spell checkers.
  • Polar SpellChecker Component offers autocorrection and "as you type" mode, and it comes with full source code and dictionaries for 14 languages.

Help Users Help Themselves

Spell checkers are plentiful and easy to integrate, so why not enable your interactive application to help users look a little smarter (or less clumsy, if you prefer) through a helpful dialog or two. Give GPP Spellchecker a try for your basic spelling needs.

About the Author

Victor Volkman has been writing for C/C++ Users Journal and other programming journals since the late 1980s. He is a graduate of Michigan Tech and a faculty advisor board member for Washtenaw Community College CIS department. Volkman is the editor of numerous books, including C/C++ Treasure Chest and is the owner of Loving Healing Press. He can help you in your quest for open source tools and libraries, just drop an e-mail to sysop@HAL9K.com.



About the Author

Victor Volkman

Victor Volkman has been writing for C/C++ Users Journal and other programming journals since the late 1980s. He is a graduate of Michigan Tech and a faculty advisor board member for Washtenaw Community College CIS department. Volkman is the editor of numerous books, including C/C++ Treasure Chest and is the owner of Loving Healing Press. He can help you in your quest for open source tools and libraries, just drop an e-mail to sysop@HAL9K.com.

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: September 10, 2014 Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild." This loop of continuous delivery and continuous feedback is how the best mobile …

  • As mobile devices have pushed their way into the enterprise, they have brought cloud apps along with them. This app explosion means account passwords are multiplying, which exposes corporate data and leads to help desk calls from frustrated users. This paper will discover how IT can improve user productivity, gain visibility and control over SaaS and mobile apps, and stop password sprawl. Download this white paper to learn: How you can leverage your existing AD to manage app access. Key capabilities to …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds