//========================================================================
//TITLE:
// 漫谈WinCE的手写识别技术(二)
//AUTHOR:
// norains
//DATE:
// Thursday 25-January -2007
//Environment:
// EVC4.0 + Standard SDK
//========================================================================
在第一章的时候,已经介绍了识别的一般性过程,对于实际运用来说,是完全可行的;但从便利性角度出发,却不免显得烦琐:每次输入笔画都需留意点阵是否屏幕坐标系,每次读取返回的字符总要分配内存然后获取等等,诸如总总,代码写一次还好,如果多处运用多次编写多方维护,实在不是一件快乐的事情.
而我,最讨厌做复杂又要花费脑筋的东东;所以,为了让自己感觉得写代码是一件快乐的事情,自己又很高兴地将识别过程封装为一个类.至于是否达到简便的效果,不敢祈求大家苟同,只愿自己舒坦即可.


/**///////////////////////////////////////////////////////////////////////
// Recognizer.h: interface for the CRecognizer class. //

/**///////////////////////////////////////////////////////////////////////
#ifndef RECOGNIZER_H
#define RECOGNIZER_H

//===========================================================================
//Include file
#include "recog.h"

//=====================================================================================
//Choose the build type for the recognizing function
//--------------------------------------------------------------------------
#define RECOGNIZE_FUNCTION_FROM_DLL
//#define RECOGNIZE_FUNCTION_FROM_LIB

#ifndef RECOGNIZE_FUNCTION_FROM_LIB
#ifndef RECOGNIZE_FUNCTION_FROM_DLL
#define RECOGNIZE_FUNCTION_FROM_DLL
#endif
#endif

#ifdef RECOGNIZE_FUNCTION_FROM_DLL
#define RECOGNIZE_DLL_PATH TEXT("\WINDOWS\hwxcht.dll")
#endif
//=====================================================================================



//-----------------------------------------------------------------------------------
//The data type

//The scale type for the coordinate
enum ScaleType

...{
SCALE_APPWND,
SCALE_SCREEN
};
//------------------------------------------------------------------------------
class CRecognizer

...{
public:
BOOL InputStroke(POINT *lpPnt, int iCount, ScaleType scale);
CRecognizer();
virtual ~CRecognizer();
int GetCharacter(WCHAR *pWchar, int iCount);
BOOL EndRecognize();
BOOL BeginRecognize();
BOOL Initialize(HWND hWnd,const RECT *prcWnd,ScaleType scale);
protected:
HRC m_hrc;
HWXGUIDE m_hwxGuide;
HWND m_hWndRecog;
ALC m_alc;

#ifdef RECOGNIZE_FUNCTION_FROM_DLL
typedef BOOL (WINAPI *DLL_HWXCONFIG)(void);
typedef HRC (WINAPI *DLL_HWXCREATE)(HRC = NULL);
typedef BOOL (WINAPI *DLL_HWXSETGUIDE)(HRC ,HWXGUIDE*);
typedef BOOL (WINAPI *DLL_HWXALCVALID)(HRC,ALC);
typedef BOOL (WINAPI *DLL_HWXALCPRIORITY)(HRC,ALC);
typedef BOOL (WINAPI *DLL_HWXSETCONTEXT)(HRC,WCHAR);
typedef BOOL (WINAPI *DLL_HWXINPUT)(HRC,POINT*,UINT, DWORD);
typedef BOOL (WINAPI *DLL_HWXENDINPUT)(HRC);
typedef BOOL (WINAPI *DLL_HWXPROCESS)(HRC);
typedef INT (WINAPI *DLL_HWXRESULTSAVAILABLE)(HRC);
typedef INT32 (WINAPI *DLL_HWXGETRESULTS)(HRC, UINT, UINT, UINT, HWXRESULTS*);
typedef BOOL (WINAPI *DLL_HWXDESTROY)(HRC);
DLL_HWXCONFIG HWXCONFIG;
DLL_HWXCREATE HWXCREATE;
DLL_HWXSETGUIDE HWXSETGUIDE;
DLL_HWXALCVALID HWXALCVALID;
DLL_HWXALCPRIORITY HWXALCPRIORITY;
DLL_HWXSETCONTEXT HWXSETCONTEXT;
DLL_HWXINPUT HWXINPUT;
DLL_HWXPROCESS HWXPROCESS;
DLL_HWXRESULTSAVAILABLE HWXRESULTSAVAILABLE;
DLL_HWXGETRESULTS HWXGETRESULTS;
DLL_HWXDESTROY HWXDESTROY;
DLL_HWXENDINPUT HWXENDINPUT;
#endif //RECOGNIZE_FUNCTION_FROM_DLL


#ifdef RECOGNIZE_FUNCTION_FROM_LIB
#define HWXCONFIG(void) HwxConfig(void)
#define HWXCREATE(hrc) HwxCreate(hrc)
#define HWXSETGUIDE(hrc,lpGuide) HwxSetGuide(hrc,lpGuide)
#define HWXALCVALID(hrc,alc) HwxALCValid(hrc,alc)
#define HWXALCPRIORITY(hrc,alc) HwxALCPriority(hrc,alc)
#define HWXSETCONTEXT(hrc,wContext) HwxSetContext(hrc,wContext)
#define HWXINPUT(hrc,lppnt,upoints,timestamp) HwxInput(hrc,lppnt,upoints,timestamp)
#define HWXPROCESS(hrc) HwxProcess(hrc)
#define HWXRESULTSAVAILABLE(hrc) HwxResultsAvailable(hrc)
#define HWXGETRESULTS(hrc,cAlt,iFirst,cBoxRes,rgBoxResults) HwxGetResults(hrc,cAlt,iFirst,cBoxRes,rgBoxResults)
#define HWXDESTROY(hrc) HwxDestroy(hrc)
#define HWXENDINPUT(hrc) HwxEndInput(hrc)
#endif //RECOGNIZE_FUNCTION_FROM_LIB
};



//============================================================================================
#endif // !defined RECOGNIZER_H






/**///////////////////////////////////////////////////////////////////////
// Recognizer.cpp: implementation of the CRecognizer class. //

/**///////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Recognizer.h"

//-------------------------------------------------------------------
//Macro define

//The default value of hwxGuide
#define DEFAULT_HWXGUIDE_CHORZBOX 1
#define DEFAULT_HWXGUIDE_CVERTBOX 1
#define DEFAULT_HWXGUIDE_CXOFFSET 1
#define DEFAULT_HWXGUIDE_CYOFFSET 1

//The default value of ALC
#define DEFAULT_ALC ALC_KANJI_ALL




//--------------------------------------------------------------------

/**///////////////////////////////////////////////////////////////////////
// Construction/Destruction

/**///////////////////////////////////////////////////////////////////////
CRecognizer::CRecognizer()

...{
m_alc = NULL;
m_hrc = NULL;
m_hWndRecog = NULL;
memset(&m_hwxGuide,0,sizeof(m_hwxGuide));
}

CRecognizer::~CRecognizer()

...{

}

//-----------------------------------------------------------------------
//Descriptiong:
// Initialize the recognizer
//
//Parameter:
// hWnd: [in] The handle of window to be recognized
// rcWnd: [in] The window area to be recognized
// scale: [in] The scale base of prcWnd point
//-----------------------------------------------------------------------
BOOL CRecognizer::Initialize(HWND hWnd,const RECT *prcWnd,ScaleType scale)

...{
m_hWndRecog = hWnd;

m_alc = DEFAULT_ALC;


RECT rcWnd = ...{0};
switch(scale)

...{
case SCALE_APPWND:

...{
rcWnd = *prcWnd;
rcWnd.left *= 4;
rcWnd.right *= 4;
rcWnd.top *= 4;
rcWnd.bottom *= 4;
MapWindowPoints(hWnd,HWND_DESKTOP,(LPPOINT)(&rcWnd),(sizeof(RECT)/sizeof(POINT)));
break;
}
case SCALE_SCREEN:

...{
rcWnd = *prcWnd;
break;
}
}

m_hwxGuide.cHorzBox = DEFAULT_HWXGUIDE_CHORZBOX;
m_hwxGuide.cVertBox = DEFAULT_HWXGUIDE_CVERTBOX;
m_hwxGuide.xOrigin = rcWnd.left;
m_hwxGuide.yOrigin = rcWnd.top;
m_hwxGuide.cxBox = rcWnd.right - rcWnd.left;
m_hwxGuide.cyBox = rcWnd.bottom - rcWnd.top;
m_hwxGuide.cxOffset = DEFAULT_HWXGUIDE_CXOFFSET;
m_hwxGuide.cyOffset = DEFAULT_HWXGUIDE_CYOFFSET;
m_hwxGuide.cxWriting = (rcWnd.right - rcWnd.left) - m_hwxGuide.cxOffset * 2;
m_hwxGuide.cyWriting = (rcWnd.bottom - rcWnd.top) - m_hwxGuide.cyOffset * 2;
m_hwxGuide.nDir = HWX_HORIZONTAL;

#ifdef RECOGNIZE_FUNCTION_FROM_DLL
HINSTANCE hInstDll;
hInstDll = LoadLibrary(RECOGNIZE_DLL_PATH);
if(hInstDll != NULL)

...{
HWXCONFIG = (DLL_HWXCONFIG) GetProcAddress(hInstDll,TEXT("HwxConfig"));
HWXCREATE = (DLL_HWXCREATE) GetProcAddress(hInstDll,TEXT("HwxCreate"));
HWXSETGUIDE = (DLL_HWXSETGUIDE) GetProcAddress(hInstDll,TEXT("HwxSetGuide"));
HWXALCVALID = (DLL_HWXALCVALID) GetProcAddress(hInstDll,TEXT("HwxALCValid"));
HWXALCPRIORITY = (DLL_HWXALCPRIORITY) GetProcAddress(hInstDll,TEXT("HwxALCPriority"));
HWXSETCONTEXT = (DLL_HWXSETCONTEXT) GetProcAddress(hInstDll,TEXT("HwxSetContext"));
HWXINPUT = (DLL_HWXINPUT) GetProcAddress(hInstDll,TEXT("HwxInput"));
HWXPROCESS = (DLL_HWXPROCESS) GetProcAddress(hInstDll,TEXT("HwxProcess"));
HWXRESULTSAVAILABLE = (DLL_HWXRESULTSAVAILABLE) GetProcAddress(hInstDll,TEXT("HwxResultsAvailable"));
HWXGETRESULTS = (DLL_HWXGETRESULTS) GetProcAddress(hInstDll,TEXT("HwxGetResults"));
HWXDESTROY = (DLL_HWXDESTROY) GetProcAddress(hInstDll,TEXT("HwxDestroy"));
HWXENDINPUT = (DLL_HWXENDINPUT) GetProcAddress(hInstDll,TEXT("HwxEndInput"));
}
else

...{
return FALSE;
}
#endif //RECOGNIZE_FUNCTION_FROM_DLL

if(HWXCONFIG() == FALSE)

...{
return FALSE;
}

return TRUE;
}


//-----------------------------------------------------------------------
//Descriptiong:
// Begin recognizing
//-----------------------------------------------------------------------
BOOL CRecognizer::BeginRecognize()

...{
BOOL bRes = FALSE;

m_hrc = HWXCREATE();
if(m_hrc == NULL)

...{
goto END;
}

bRes = HWXSETGUIDE(m_hrc,&m_hwxGuide);
if(bRes == FALSE)

...{
goto END;
}
bRes = HWXALCVALID(m_hrc,m_alc);
if(bRes == FALSE)

...{
goto END;
}

bRes = TRUE;

END:
return bRes;
}


//-----------------------------------------------------------------------
//Descriptiong:
// End recognizing
//-----------------------------------------------------------------------
BOOL CRecognizer::EndRecognize()

...{
BOOL bRes = FALSE;

//Destroy the recognizer
if(HWXDESTROY(m_hrc) == FALSE)

...{
goto END;
}

bRes = TRUE;

END:
return bRes;
}


//-----------------------------------------------------------------------
//Descriptiong:
// Get the character
//
//Parameters:
// pWchar: [out] The character get to be stored
// iCount: [in] The number of pWchar
//
//Return Values:
// 0: Failed
// >0: The number of the characters to return
//-----------------------------------------------------------------------
int CRecognizer::GetCharacter(WCHAR *pWchar, int iCount)

...{
int iGetNum = 0;
int i = 0;
HWXRESULTS *phwxResults;
//Because each HWXRESULTS after the first one could store two characters,
//so only allocate (iCount / 2 + 1)
int iNum = iCount / 2 + 1;
phwxResults = new HWXRESULTS[iNum];
memset(phwxResults,0,iNum * sizeof(HWXRESULTS));

//End the input
if(HWXENDINPUT(m_hrc) == FALSE)

...{
goto END;
}

//Analyze the information
if(HWXPROCESS(m_hrc) == FALSE)

...{
goto END;
}



//Get the character from recognizer
if(HWXGETRESULTS(m_hrc,iCount,0,1,phwxResults) == FALSE)

...{
goto END;
}

//Set the character to the stored buffer
for(i = 0; i < iNum; i++)

...{
if(i == 0)

...{
if(phwxResults[i].rgChar[0] != 0)

...{
pWchar[iGetNum ++] = phwxResults[i].rgChar[0];
}
else
![]()