- 收藏
- 点赞
- 分享
- 举报
手写软件设计技术2
[code] 在第一章的时候,已经介绍了识别的一般性过程,对于实际运用来说,是完全可行的;但从便利性角度出发,却不免显得烦琐:每次输入笔画都需留意点阵是否屏幕坐标系,每次读取返回的字符总要分配内存然后获取等等,诸如总总,代码写一次还好,如果多处运用多次编写多方维护,实在不是一件快乐的事情.
而我,最讨厌做复杂又要花费脑筋的东东;所以,为了让自己感觉得写代码是一件快乐的事情,自己又很高兴地将识别过程封装为一个类.至于是否达到简便的效果,不敢祈求大家苟同,只愿自己舒坦即可.
//////////////////////////////////////////////////////////////////////// // 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.rgChar[0] != 0)
...{
pWchar[iGetNum ++] = phwxResults.rgChar[0];
}
else
...{
break;
}
}
else
...{
//The indxBox member also store the character
if(phwxResults.indxBox != 0)
...{
pWchar[iGetNum ++] = phwxResults.indxBox ;
}
else
...{
break;
}
if(phwxResults.rgChar[0] != 0)
...{
pWchar[iGetNum ++] = phwxResults.rgChar[0];
}
else
...{
break;
}
}
}
END: if(phwxResults != NULL) ...{ delete [] phwxResults; } return iGetNum; } //----------------------------------------------------------------------- //Descriptiong: // Input the stroke // //Parameter: // lpPnt: [in] ointer to the stroke OINT // iCount: [in] The count of the lpPnt // scale: [in] The scale base of lpPnt //----------------------------------------------------------------------- BOOL CRecognizer::InputStroke(POINT *lpPnt, int iCount, ScaleType scale) ...{ BOOL bRes = FALSE; int i = 0;
OINT *pt;
pt = new OINT[iCount];
if(pt == NULL)
...{
goto END;
}
for(i = 0; i < iCount; i++)
...{
pt = lpPnt;
if(scale == SCALE_APPWND)
...{
//Convert to the screen scale
pt.x *= 4;
pt.y *= 4;
MapWindowPoints(m_hWndRecog, HWND_DESKTOP, &pt, 1);
}
}
//Input stroke
bRes = HWXINPUT(m_hrc,pt,iCount,0);
if(bRes == FALSE)
...{
goto END;
}
bRes = TRUE;
END: if(pt != NULL) ...{ delete [] pt; } return bRes; }
不知道大家看到这段代码有什么感觉,反正我是挺高兴的,因为让我从繁琐的识别过程中脱离出来.
关于代码,也许最让人疑惑的可能是这两个宏:RECOGNIZE_FUNCTION_FROM_DLL,RECOGNIZE_FUNCTION_FROM_LIB.
顾名思义,RECOGNIZE_FUNCTION_FROM_DLL表明识别函数调用是来源于动态链接库(DLL),同理,RECOGNIZE_FUNCTION_FROM_LIB则是编译的时候链接到lib库.为什么需要定义这两个宏呢?因为在标准的SDK下,如果直接包含"recog.h"后调用相关识别函数,是会报link错误.因为标准的SDK是不包含任何手写识别组件的.从调试的便利性来说,这时候如果只拷贝识别库到模拟器就可以顺利测试程序,绝对比重新定制一个包含手写识别引擎的系统要来得方便.
在示例代码中,因为是识别繁体中文,所以包含的动态链接库为:hwxcht.dll.如果需要识别其它文字,则只要更改该动态链接库名称即可.当然,还要更改DEFAULT_ALC宏,这个宏定义了识别的范围.
因为示例代码中的识别函数全部是宏定义,具体意义根据函数的来源而不同,所以RECOGNIZE_FUNCTION_FROM_DLL和RECOGNIZE_FUNCTION_FROMLIB同一时间只能定义一个.如果两个都定义,毫无疑问,出错!^^
最后,用伪代码做范例说明如何使用该封装类,以此做本章结尾: CRecognizer recog;
Rect rcWnd;
/**//*rcWnd 获取应用窗口hWnd的大小*/
//初始化
//直接赋值窗口坐标,函数体内部会根据标志直接转换为屏幕坐标
recog.Initialize(hWnd,&rcWnd,SCALE_APPWND);
//开始识别
recog.BeginRecognize();
OINT pt[200];
int iCount = 0;
/**//*获取笔画坐标给pt,坐标的数量储存在iCount中*/
//将笔画点阵传送给识别引擎
//如果有多个笔画,则每个笔画都需要调用该函数进行传入
recog.InputStroke(pt,iCount,SCALE_APPWND);
//获取十个最接近的字符,iReturn是实际返回的字符数
WCHAR wChar[10];
int iReturn = recog.GetCharacter(wChar,10);
//结束识别
recog.EndRecognize();
/**//*如果
//======================================================================== //TITLE: // 漫谈WinCE输入法的编写(三) //AUTHOR: // norains //DATE: // Friday 2-March -2007 //Environment: // EVC4.0 + Standard SDK //========================================================================
这次就让我们来看看一个简单的输入法界面窗口的实现.如果以类的观点来看,输入法界面窗口和普通的应用程序的窗口没有什么不同,可能也是唯一最大的差异就是输入法窗口不能也不应该发送PostQuiteMessage,否则将导致输入法管理器的退出.
闲话不表,直接来看看一个最简单的输入法窗口架构: //**************************************************************
//IMWnd.h
//*************************************************************
//The input method window class
class CIMWnd
...{
public:
//获取对象实例
static CIMWnd * GetInstance();
//显示输入法的设置窗口
void ShowUserOptionsDlg(HWND hWndParent,HINSTANCE hInst = NULL);
//显示输入法界面
void ShowWindow(BOOL bShow);
//销毁输入法界面
void DestroyWindow();
//初始化窗口,hWndSip是输入法管理器的句柄
BOOL Initialize(HINSTANCE hInst, HWND hWndSip);
//析构函数
virtual ~CIMWnd();
protected:
//构造函数
CIMWnd();
//注册回调函数
void OnRegCallback(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam);
//窗口过程
static LRESULT WndProc(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM lParam);
//指向对象的指针
static CIMWnd *m_pInstance;
//输入法窗口句柄
HWND m_hWnd;
//DLL实例
HINSTANCE m_hInst;
//输入法管理器窗口句柄
HWND m_hWndSip;
//保存对外回调函数的指针
IIMCallback *m_pIMCallback; //Pointer to the callback function
};
//**************************************************************
//IMWnd.cpp
//*************************************************************
//Initialize
CIMWnd *CIMWnd::m_pInstance = NULL;
//----------------------------------------------------------------------
//Description:
// Get the object instance
//----------------------------------------------------------------------
CIMWnd * CIMWnd::GetInstance()
...{
if(m_pInstance == NULL)
...{
m_pInstance = new CIMWnd();
}
return m_pInstance;
}
//----------------------------------------------------------------------------
//Decription:
// On message MSG_USEROPTIONSDLG
//-----------------------------------------------------------------------------
void CIMWnd::ShowUserOptionsDlg(HWND hWndParent,HINSTANCE hInst)
...{
CSettingDlg *pSettingDlg;
pSettingDlg = CSettingDlg::GetInstance();
if(hInst == NULL)
...{
pSettingDlg->ShowDlg(m_hInst,hWndParent,&m_iTimeFresh);
}
else
...{
pSettingDlg->ShowDlg(hInst,hWndParent,&m_iTimeFresh);
}
}
//---------------------------------------------------------------------- //Description: // Show the window //---------------------------------------------------------------------- void CIMWnd::ShowWindow(BOOL bShow) ...{ if(bShow == TRUE) ...{ ::ShowWindow(m_hWnd,SW_SHOW); } else ...{ ::ShowWindow(m_hWnd,SW_HIDE); } }
//----------------------------------------------------------------------
//Description:
// Destroy the window
//----------------------------------------------------------------------
void CIMWnd:estroyWindow()
...{
:estroyWindow(m_hWnd);
UnregisterClass(WINDOW_CLASS,m_hInst);
}
//----------------------------------------------------------------------
//Description:
// Initialize
//----------------------------------------------------------------------
BOOL CIMWnd::Initialize(HINSTANCE hInst, HWND hWndSip)
...{
m_hInst = hInst;
m_hWndSip = hWndSip;
WNDCLASS wc;
wc.style = CS_VREDRAW | CS_HREDRAW;;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = WINDOW_CLASS;
if(RegisterClass(&wc) == 0)
...{
return FALSE;
}
// Create SIP window.
m_hWnd = CreateWindowEx(0,
WINDOW_CLASS,
WINDOW_TITLE,
WS_CHILD | WS_BORDER ,
CW_USERDEFAULT,
CW_USERDEFAULT,
CW_USERDEFAULT,
CW_USERDEFAULT,
hWndSip,
NULL,
m_hInst,
NULL
);
if(IsWindow(m_hWnd)==FALSE)
...{
return FALSE;
}
return TRUE;
}
CIMWnd::~CIMWnd()
...{
DeleteCriticalSection(&m_CriticalForWaitFresh);
if(m_pInstance != NULL)
...{
delete m_pInstance;
m_pInstance = NULL;
}
}
CIMWnd::CIMWnd()
...{
m_pIMCallback = NULL;
m_hWnd = NULL;
m_hInst = NULL;
m_hWndSip = NULL;
}
//---------------------------------------------------------------------------- //De
Markdown 语法
- 加粗**内容**
- 斜体*内容*
- 删除线~~内容~~
- 引用> 引用内容
- 代码`代码`
- 代码块```编程语言↵代码```
- 链接[链接标题](url)
- 无序列表- 内容
- 有序列表1. 内容
- 缩进内容
- 图片![alt](url)
-
2008-12-29 17:36:43
-
2020-08-27 17:55:26
-
2013-08-29 19:30:21
-
2016-01-13 18:27:29
-
2018-09-17 09:51:08
-
2023-10-13 16:25:01
-
2018-09-14 11:25:46
-
2023-08-14 09:25:22
-
2012-12-24 15:14:50
-
2012-12-24 14:17:53
-
2018-12-18 17:00:57
-
2016-04-18 15:57:11
-
2017-11-06 09:49:22
-
2013-11-29 23:02:26
-
2020-08-13 17:26:54
-
2018-12-13 11:15:22
-
2020-09-29 14:42:26
-
2020-09-29 14:41:50
-
2019-04-11 10:37:41
-
5Hi3516CV610 如何使用SD卡升级固件
-
5cat /dev/logmpp 报错 <3>[ vi] [func]:vi_send_frame_node [line]:99 [info]:vi pic queue is full!
-
50如何获取vpss chn的图像修改后发送至vo
-
5FPGA通过Bt1120传YUV422数据过来,vi接收不到数据——3516dv500
-
50SS928 运行PQtools 拼接 推到设备里有一半画面会异常
-
53536AV100的sample_vdec输出到CVBS显示
-
10海思板子mpp怎么在vi阶段改变视频数据尺寸
-
10HI3559AV100 多摄像头同步模式
-
9海思ss928单路摄像头vio中加入opencv处理并显示
-
10EB-RV1126-BC-191板子运行自己编码的程序
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明