Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version
Go to top

A Spell Checking Engine

, 5 Feb 2001
A free spell checking engine for use in your C++ applications. Includes the current US English dictionary
/*

  Copyright:		2000
  Author:			Matthew T Gullett
  Email:			gullettm@yahoo.com
  Name:				CFPSSpellingEditCtrl
  Part of:			Spell Checking Engine 
  Requires:			

  DESCRIPTION
  ----------------------------------------------------------
  This class is designed to implement a self spell-checking
  edit control.  It utilized the FPS Spell Checking Engine
  to provide dictionary and suggestion support.


  INFO:
  ----------------------------------------------------------
  This class is provided -as is-.  No warranty as to the
  function or performance of this class is provided either 
  written or implied.  
  
  You may freely use this code and modify it as necessary,
  as long as this header is unmodified and credit is given
  to the author in the application(s) in which it is
  incorporated.

*/

#include "stdafx.h"
#include "FPSSpellChecker.h"
#include "FPSSpellingEditCtrl.h"

#include "FPSSpellCheckEngine.h"
#include "DlgSpellChecker.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// define the maximum # of suggestions to display on popup-menu
#define CFPSSpellingEditCtrl_MAX_SUGGEST		10


// here, I define the COMMAND IDs used in the context menu for
// selecting a desired suggestion.
#define APSTUDIO_INVOKED
#undef APSTUDIO_READONLY_SYMBOLS
#include "resource.h"
#define ID_SPELL_WORD1		_APS_NEXT_COMMAND_VALUE+1
#define ID_SPELL_WORD2		ID_SPELL_WORD1+1
#define ID_SPELL_WORD3		ID_SPELL_WORD1+2
#define ID_SPELL_WORD4		ID_SPELL_WORD1+3
#define ID_SPELL_WORD5		ID_SPELL_WORD1+4
#define ID_SPELL_WORD6		ID_SPELL_WORD1+5
#define ID_SPELL_WORD7		ID_SPELL_WORD1+6
#define ID_SPELL_WORD8		ID_SPELL_WORD1+7
#define ID_SPELL_WORD9		ID_SPELL_WORD1+8
#define ID_SPELL_WORD10		ID_SPELL_WORD1+9

#define ID_SPELL_IGNORE		_APS_NEXT_COMMAND_VALUE+21
#define ID_SPELL_IGNORE_ALL	_APS_NEXT_COMMAND_VALUE+22
#define ID_SPELL_ADD		_APS_NEXT_COMMAND_VALUE+23
#define APSTUDIO_READONLY_SYMBOLS
#undef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
// CFPSSpellingEditCtrl

CFPSSpellingEditCtrl::CFPSSpellingEditCtrl()
{
	m_bErrorsDrawn = FALSE;
	m_dwLastTick = 0;
	m_uiTimerID = 0;

	m_pCurrentSel = NULL;
}

CFPSSpellingEditCtrl::~CFPSSpellingEditCtrl()
{
	ClearSpellingErrors();
}

CFPSSpellCheckEngine* CFPSSpellingEditCtrl::m_pEngine = NULL;
FPSSPELLEDIT_HOTKEY CFPSSpellingEditCtrl::m_HotKey;

BEGIN_MESSAGE_MAP(CFPSSpellingEditCtrl, CEdit)
	//{{AFX_MSG_MAP(CFPSSpellingEditCtrl)
	ON_WM_PAINT()
	ON_CONTROL_REFLECT(EN_CHANGE, OnChange)
	ON_WM_VSCROLL()
	ON_WM_HSCROLL()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_DESTROY()
	ON_WM_TIMER()
	ON_WM_KEYDOWN()
	ON_WM_RBUTTONUP()
	ON_CONTROL_REFLECT(EN_UPDATE, OnUpdate)
	ON_WM_CREATE()
	ON_WM_ERASEBKGND()
	//}}AFX_MSG_MAP
	ON_COMMAND_RANGE(ID_SPELL_WORD1, ID_SPELL_WORD10, ReplaceSpellingError)
	ON_COMMAND(ID_EDIT_UNDO, Undo)
	ON_COMMAND(ID_EDIT_CUT, Cut)
	ON_COMMAND(ID_EDIT_COPY, Copy)
	ON_COMMAND(ID_EDIT_PASTE, Paste)
	ON_COMMAND(ID_EDIT_SELECT_ALL, SelectAll)
	ON_COMMAND(ID_SPELL_ADD, OnAddWord)
	ON_COMMAND(ID_SPELL_IGNORE, OnIgnoreWord)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFPSSpellingEditCtrl message handlers

void CFPSSpellingEditCtrl::OnPaint() 
{
	CEdit::OnPaint();

	if (m_bErrorsDrawn)
		RedrawSpellingErrors();
}

void CFPSSpellingEditCtrl::OnChange() 
{
	InvalidateSpellCheck();
}

void CFPSSpellingEditCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{	
	if (m_bErrorsDrawn)
	{
		m_bErrorsDrawn = FALSE;
		RedrawWindow();

		CEdit::OnVScroll(nSBCode, nPos, pScrollBar);

		m_bErrorsDrawn = TRUE;
		RedrawSpellingErrors();
	}
	else
	{
		CEdit::OnVScroll(nSBCode, nPos, pScrollBar);
	}
}

void CFPSSpellingEditCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{	
	if (m_bErrorsDrawn)
	{
		CEdit::OnHScroll(nSBCode, nPos, pScrollBar);

		m_bErrorsDrawn = TRUE;
		RedrawSpellingErrors();
	}
	else
	{
		CEdit::OnHScroll(nSBCode, nPos, pScrollBar);
	}
}

void CFPSSpellingEditCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
{	
	CEdit::OnLButtonDown(nFlags, point);

	if (m_bErrorsDrawn)
		RedrawSpellingErrors();
}

void CFPSSpellingEditCtrl::OnLButtonUp(UINT nFlags, CPoint point) 
{	
	CEdit::OnLButtonUp(nFlags, point);

	if (m_bErrorsDrawn)
		RedrawSpellingErrors();
}

void CFPSSpellingEditCtrl::RedrawSpellingErrors()
{
	if (IsPaintErrorsOK())
	{
		CClientDC dc(this);
		CString strText;
		int iLine = GetFirstVisibleLine();
		int iChar = LineIndex(iLine);
		int iLineLen = LineLength(iLine);
		int iLineCount = GetLineCount();
		CRect ClientRect;
		BOOL bContinue = TRUE;

		ClearSpellingErrors();

		GetWindowText(strText);

		GetClientRect(ClientRect);

		while (bContinue)
		{
			if (iLineLen > 0 && iChar != -1)
				RedrawSpellingErrors(iLine, iLineLen, iChar, strText, dc);

			iLine++;

			if (iLine > iLineCount)
			{
				bContinue = FALSE;
			}
			else
			{
				iLineLen = LineLength(iLine);
				iChar = LineIndex(iLine);

				POINT pt = PosFromChar(iChar);
				if (pt.y > ClientRect.Height())
					bContinue = FALSE;
				if (iLine >= iLineCount)
					bContinue = FALSE;
			}
		}
	}
}

void CFPSSpellingEditCtrl::RedrawSpellingErrors(int iLine, int iLineLen, int iChar, LPCSTR lpszText, CClientDC& dc)
{
	ASSERT(lpszText);
	ASSERT(AfxIsValidString(lpszText));
	ASSERT(iLine >= 0);
	ASSERT(iLineLen >= 0);
	ASSERT(iChar >= 0);

	CString strWord;
	int iLineBegins = -1;
	char cThisChar = 0;
	int iCharPos = iChar;

	// extract words from line
	while (lpszText[iCharPos] != 0 && lpszText[iCharPos] != '\r' && lpszText[iCharPos] != '\n')
	{
		cThisChar = lpszText[iCharPos];

		if (IsWordBreak(cThisChar))
		{
			strWord.TrimLeft();
			strWord.TrimRight();

			if (strWord != "")
				DrawSpellingError(strWord, iLineBegins, dc);

			strWord = "";
			iLineBegins = -1;
		}
		else
		{
			strWord += lpszText[iCharPos];
			if (iLineBegins == -1 && strWord != "")
				iLineBegins = iCharPos;
		}

		iCharPos++;
	}

	if (strWord != "")
	{
		strWord.TrimLeft();
		strWord.TrimRight();

		if (strWord != "")
			DrawSpellingError(strWord, iLineBegins, dc);
	}
}

void CFPSSpellingEditCtrl::DrawSpellingError(LPCSTR lpszWord, int iChar, CClientDC& dc)
{
	ASSERT(lpszWord);
	ASSERT(AfxIsValidString(lpszWord));
	ASSERT(iChar >= 0);
	ASSERT(m_pEngine);

	CStringList Suggestions;

	if (!m_pEngine)
		return;
	if (m_pEngine->FindWord(lpszWord, Suggestions, FALSE) || (lstrlen(lpszWord) == 0 && IsVowel(lpszWord[0])))
		return;

	CFont* pFont = GetFont();
	CFont* pOldFont = NULL;
	CBrush* pNewBrush = NULL;
	CBrush* pOldBrush = NULL;
	CPen* pNewPen = NULL;
	CPen* pOldPen = NULL;
	CSize szWord;
	int iY = 0;

	pOldFont = dc.SelectObject(pFont);
	ASSERT(pOldFont);
	try
	{
		pNewBrush = new CBrush;
	}
	catch(...)
	{
		pNewBrush = NULL;
	}
	ASSERT(pNewBrush);
	VERIFY(pNewBrush->CreateSolidBrush(RGB(255,0,0)));
	try
	{
		pNewPen = new CPen;
	}
	catch(...)
	{
		pNewPen = NULL;
	}
	ASSERT(pNewPen);
	VERIFY(pNewPen->CreatePen(PS_SOLID, 1, RGB(255,0,0)));

	szWord = dc.GetTextExtent(lpszWord);
	pOldBrush = dc.SelectObject(pNewBrush);
	pOldPen = dc.SelectObject(pNewPen);

	CPoint pt = PosFromChar(iChar);
	iY = pt.y + szWord.cy;

	DrawSquigly(dc, pt.x, szWord.cx, iY);

	dc.SelectObject(pOldFont);
	dc.SelectObject(pOldBrush);
	dc.SelectObject(pOldPen);

	try
	{
		delete pNewPen;
	}
	catch(...)
	{
		ASSERT(FALSE);
	}
	pNewPen = NULL;
	try
	{
		delete pNewBrush;
	}
	catch(...)
	{
		ASSERT(FALSE);
	}
	pNewPen = NULL;

	// create a new spelling error record
	FPSSPELLEDIT_ERRORS* pNewError = NULL;
	try
	{
		pNewError = new FPSSPELLEDIT_ERRORS;
	}
	catch(...)
	{
		pNewError = NULL;
	}
	ASSERT(pNewError);

	m_SpellingErrors.AddTail(pNewError);
	pNewError->strWord = lpszWord;
	pNewError->rctArea.SetRect(pt.x, pt.y, pt.x + szWord.cx, iY);
	pNewError->iChar = iChar;
}

void CFPSSpellingEditCtrl::DrawSquigly(CDC &dc, int iLeftX, int iWidth, int iY)
{
	int iCurrentY = iY;
	int iCurrentX = iLeftX;

	CRect ClientRect;

	GetClientRect(ClientRect);


	while (iCurrentX <= iLeftX + iWidth)
	{
		dc.MoveTo(iCurrentX, iY);
		if (iCurrentX+2 <= iLeftX + iWidth && iY+2 < ClientRect.Width())
			dc.LineTo(iCurrentX+2, iY+2);
		if (iCurrentX+4 <= iLeftX + iWidth && iY+2 < ClientRect.Width())
			dc.LineTo(iCurrentX+4, iY);

		iCurrentX += 3;
	}
}

void CFPSSpellingEditCtrl::ClearSpellingErrors()
{
	FPSSPELLEDIT_ERRORS* pEntry = NULL;
	POSITION Pos = NULL;

	Pos = m_SpellingErrors.GetHeadPosition();
	while (Pos)
	{
		pEntry = m_SpellingErrors.GetNext(Pos);
		ASSERT(pEntry);
		try
		{
			delete pEntry;
		}
		catch(...)
		{
			ASSERT(FALSE);
		}
		pEntry = NULL;
	}
	m_SpellingErrors.RemoveAll();
}

void CFPSSpellingEditCtrl::OnDestroy() 
{
	CEdit::OnDestroy();
	
	KillTimer(1);
	KillTimer(m_uiTimerID);
}

void CFPSSpellingEditCtrl::OnTimer(UINT nIDEvent) 
{
	KillTimer(1);
	KillTimer(m_uiTimerID);

	// if timer event is the spell checker event, check it now
	if (nIDEvent == m_uiTimerID)
	{
		DWORD dwCount = GetTickCount() - m_dwLastTick;

		if (dwCount > FPSSPELLEDIT_SPELL_CHECK_WAIT && !m_bErrorsDrawn)
		{
			RedrawSpellingErrors();
			m_bErrorsDrawn = TRUE;
		}
	}

	m_uiTimerID = SetTimer(1, 10, NULL);
	
	CEdit::OnTimer(nIDEvent);
}

void CFPSSpellingEditCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	InvalidateSpellCheck();	
	CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
}

void CFPSSpellingEditCtrl::InvalidateSpellCheck()
{
	if (m_bErrorsDrawn)
	{
		m_SpellingMatches.RemoveAll();
		m_pCurrentSel = NULL;
		m_bErrorsDrawn = FALSE;
		RedrawWindow();
		UpdateWindow();
	}
	m_dwLastTick = ::GetTickCount();
}

BOOL CFPSSpellingEditCtrl::PreTranslateMessage(MSG* pMsg) 
{
	ASSERT(pMsg);

	// create our timer when appropriate
	if (::IsWindow(GetSafeHwnd()) && m_uiTimerID == 0)
		m_uiTimerID = SetTimer(1, 10, NULL);
	
	// check for Spell Check Hot Key
	if (IsHotKey(pMsg, m_HotKey))
	{
		CheckSpelling();
		return TRUE;
	}

	return CEdit::PreTranslateMessage(pMsg);
}

FPSSPELLEDIT_ERRORS* CFPSSpellingEditCtrl::FindError(CPoint pt)
{
	FPSSPELLEDIT_ERRORS* pEntry;
	POSITION Pos;
	BOOL bFound = FALSE;

	Pos = m_SpellingErrors.GetHeadPosition();
	while (Pos && !bFound)
	{
		pEntry = m_SpellingErrors.GetNext(Pos);
		ASSERT(pEntry);

		if (pEntry->rctArea.PtInRect(pt))
			bFound = TRUE;
	}

	if (bFound)
		return pEntry;

	return NULL;
}

void CFPSSpellingEditCtrl::OnRButtonUp(UINT nFlags, CPoint point) 
{
	ASSERT(m_pEngine);

	FPSSPELLEDIT_ERRORS* pError = FindError(point);
	if (pError)
	{
		m_pCurrentSel = pError;

		int iPos = 0;
		POSITION Pos;
		CStringList Matches;
		CString strMatch;
		HANDLE hClip = ::GetClipboardData(CF_TEXT);

		if (m_pEngine)
			m_pEngine->FindWord(pError->strWord, Matches, TRUE);

		SortMatches(pError->strWord, Matches);

		m_SpellingMatches.RemoveAll();
		m_SpellingMatches.AddTail(&Matches);

		CMenu* pMenu = NULL;
		try
		{
			pMenu = new CMenu;
		}
		catch(...)
		{
			pMenu = NULL;
		}
		ASSERT(pMenu);
		VERIFY(pMenu->CreatePopupMenu());

		Pos = Matches.GetHeadPosition();
		while (Pos && iPos < CFPSSpellingEditCtrl_MAX_SUGGEST)
		{
			strMatch = Matches.GetNext(Pos);
			VERIFY(pMenu->AppendMenu(MF_STRING, ID_SPELL_WORD1+iPos, strMatch));

			iPos++;
		}
		if (Matches.GetCount() == 0)
			VERIFY(pMenu->AppendMenu(MF_STRING, 0, "No Suggestions"));
		VERIFY(pMenu->AppendMenu(MF_SEPARATOR, 0, ""));
		VERIFY(pMenu->AppendMenu(MF_STRING, ID_SPELL_ADD, "Add"));
		VERIFY(pMenu->AppendMenu(MF_STRING, ID_SPELL_IGNORE, "Ignore"));
		VERIFY(pMenu->AppendMenu(MF_SEPARATOR, 0, ""));

		if (CanUndo())
			VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_UNDO, "Undo"));
		if (IsSelection() || hClip)
		{
			VERIFY(pMenu->AppendMenu(MF_SEPARATOR, 0, ""));
			VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_CUT, "Cut"));
		}
		if (IsSelection())
			VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_COPY, "Copy"));
		if (hClip)
			VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_PASTE, "Paste"));

		VERIFY(pMenu->AppendMenu(MF_SEPARATOR, 0, ""));
		VERIFY(pMenu->AppendMenu(MF_STRING, ID_EDIT_SELECT_ALL, "Select All"));

		if (!hClip)
			::CloseHandle(hClip);
		ClientToScreen(&point);

		pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON,
								point.x, point.y,
								this);

		try
		{
			delete pMenu;
		}
		catch(...)
		{
			ASSERT(FALSE);
			TRACE("CFPSSpellingEditCtrl::OnRButtonUp failed to destroy menu resource\n");
			pMenu = FALSE;
		}
	}
	else
	{
		CEdit::OnRButtonUp(nFlags, point);
	}	
}

BOOL CFPSSpellingEditCtrl::IsSelection()
{
	BOOL bReturn = FALSE;
	int iStart = 0;
	int iEnd = 0;

	GetSel(iStart, iEnd);

	if (iStart != iEnd)
		bReturn = TRUE;

	return bReturn;
}

void CFPSSpellingEditCtrl::ReplaceSpellingError(UINT uid)
{
	if (m_pCurrentSel)
	{
		int iWord = uid - ID_SPELL_WORD1 - 1;
		CString strReplaceWord = GetReplaceWord(iWord);

		SetSel(m_pCurrentSel->iChar, m_pCurrentSel->iChar + m_pCurrentSel->strWord.GetLength());
		ReplaceSel(strReplaceWord, TRUE);

		m_bErrorsDrawn = TRUE;
		RedrawWindow();
	}
}

void CFPSSpellingEditCtrl::SelectAll()
{
	CString strText;

	GetWindowText(strText);

	SetSel(0, strText.GetLength());

	m_bErrorsDrawn = FALSE;
	RedrawWindow();
	m_bErrorsDrawn = TRUE;
	RedrawSpellingErrors();
}

CString CFPSSpellingEditCtrl::GetReplaceWord(int iPos)
{
	ASSERT(iPos >= 0);

	int iCurrent = 0;
	POSITION Pos;
	CString strTemp;

	Pos = m_SpellingMatches.GetHeadPosition();
	while (Pos && iCurrent < iPos)
	{
		strTemp = m_SpellingMatches.GetNext(Pos);

		iCurrent++;
	}

	if (iCurrent == iPos)
		return strTemp;

	return "";

}

void CFPSSpellingEditCtrl::OnUpdate() 
{
	InvalidateSpellCheck();
}

int CFPSSpellingEditCtrl::InitSpellingEngine(LPCSTR lpszConfigFile)
{
	if (lpszConfigFile)
		ASSERT(AfxIsValidString(lpszConfigFile));

	int iReturn = FPSSPELLCHECK_ERROR_NONE;

	if (m_pEngine)
	{
		try
		{
			delete m_pEngine;
		}
		catch(...)
		{
			ASSERT(FALSE);
		}
	}
	m_pEngine = NULL;

	try
	{
		m_pEngine = new CFPSSpellCheckEngine;
	}
	catch(...)
	{
		iReturn = FPSSPELLCHECK_ERROR_MEMORY;
		m_pEngine = NULL;
	}
	ASSERT(m_pEngine);
	if (m_pEngine)
		iReturn = m_pEngine->InitEngine(lpszConfigFile);

	m_HotKey.bAlt = FALSE;
	m_HotKey.bControl = FALSE;
	m_HotKey.bShift = FALSE;
	m_HotKey.uiKey = VK_F7;

	return iReturn;
}

BOOL CFPSSpellingEditCtrl::IsPaintErrorsOK()
{
	BOOL bReturn = TRUE;
	BYTE bpKeyState[255];

	memset(bpKeyState, 0, 255);

	::GetKeyboardState(bpKeyState);

	for (int iPos = 0; iPos < 255; iPos++)
	{
		if (HIBYTE(bpKeyState[iPos]) > 0)
			bReturn = FALSE;
	}

	short sL = ::GetAsyncKeyState(VK_LBUTTON);
	short sM = ::GetAsyncKeyState(VK_MBUTTON);
	short sR = ::GetAsyncKeyState(VK_RBUTTON);

	if (HIBYTE(sL) > 0 || HIBYTE(sM) > 0 || HIBYTE(sR) > 0)
		bReturn = FALSE;

	if (!m_pEngine->GetOptions().CheckWhileTyping())
		bReturn = FALSE;

	return bReturn;
}

void CFPSSpellingEditCtrl::OnAddWord()
{
	if (m_pCurrentSel)
	{
		ASSERT(m_pEngine);
		ASSERT(m_pEngine->GetUserDic());

		m_pEngine->GetUserDic()->AddWord(m_pCurrentSel->strWord);

		m_bErrorsDrawn = TRUE;
		RedrawWindow();
	}
}

void CFPSSpellingEditCtrl::OnIgnoreWord()
{
	if (m_pCurrentSel)
	{
		m_pEngine->IgnoreWord(m_pCurrentSel->strWord);

		m_bErrorsDrawn = TRUE;
		RedrawWindow();
	}
}

void CFPSSpellingEditCtrl::SetHotKey(BOOL bShift, BOOL bControl, BOOL bAlt, UINT uiKey)
{
	// set the hot key to respond to
	m_HotKey.bAlt = bAlt;
	m_HotKey.bControl = bControl;
	m_HotKey.bShift = bShift;
	m_HotKey.uiKey = uiKey;
}

void CFPSSpellingEditCtrl::CheckSpelling()
{
	// call the support function from CDlgSpellChecker
	CheckSpellingEdit(m_pEngine, this);
}

BOOL CFPSSpellingEditCtrl::IsHotKey(MSG *pMsg, FPSSPELLEDIT_HOTKEY &HotKey)
{
	ASSERT(pMsg);

	BOOL bReturn = FALSE;

	// if WM_KEYDOWN and correct KEY
	if (pMsg->message == WM_KEYDOWN && pMsg->wParam == HotKey.uiKey)
	{
		// check the states of the SHIFT, CONTROL and ALT
		// keys
		short sShift = HIBYTE(::GetKeyState(VK_SHIFT));
		short sControl = HIBYTE(::GetKeyState(VK_CONTROL));
		short sAlt = HIBYTE(::GetKeyState(VK_MENU));
		BOOL bShift = FALSE;
		BOOL bControl = FALSE;
		BOOL bAlt = FALSE;

		if (sShift == 1 && HotKey.bShift) bShift = TRUE; if (sShift == 0 && !HotKey.bShift) bShift = TRUE;
		if (sControl == 1 && HotKey.bControl) bControl = TRUE; if (sControl == 0 && !HotKey.bControl) bControl = TRUE;
		if (sAlt == 1 && HotKey.bAlt) bAlt = TRUE; if (sAlt == 0 && !HotKey.bAlt) bAlt = TRUE;

		if (bShift && bControl && bAlt)
			bReturn = TRUE;
	}

	return bReturn;
}


void CFPSSpellingEditCtrl::Terminate()
{
	if (m_pEngine)
	{
		ASSERT(m_pEngine->GetUserDic());
		m_pEngine->GetUserDic()->Save(m_pEngine->GetOptions().GetUserDic());

		try
		{
			delete m_pEngine;
		}
		catch(...)
		{
			ASSERT(FALSE);
			TRACE("CFPSSpellingEditCtrl::Terminate() delete m_pEngine failed\n");
			m_pEngine = NULL;
		}
		m_pEngine = NULL;
	}
}

void CFPSSpellingEditCtrl::AttachEdit(CWnd *pWnd, UINT uiControlID)
{
	ASSERT(!IsWindow(GetSafeHwnd()));

	ASSERT(pWnd);
	ASSERT(::IsWindow(pWnd->GetSafeHwnd()));

	CWnd* pEdit = pWnd->GetDlgItem(uiControlID);
	ASSERT(pEdit);
	ASSERT(::IsWindow(pEdit->GetSafeHwnd()));

	SubclassWindow(pEdit->GetSafeHwnd());
}

BOOL CFPSSpellingEditCtrl::OnEraseBkgnd(CDC* pDC) 
{
	
	return CWnd::OnEraseBkgnd(pDC);
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Matt Gullett
Web Developer
United States United States
No Biography provided

| Advertise | Privacy | Mobile
Web03 | 2.8.140916.1 | Last Updated 6 Feb 2001
Article Copyright 2001 by Matt Gullett
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid