aduadu

aduadu

0个粉丝

101

问答

0

专栏

45

资料

aduadu  发布于  2008-12-29 17:40:53
采纳率 0%
101个问答
3398

手写软件设计技术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

我来回答
回答0个
时间排序
认可量排序
易百纳技术社区暂无数据
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
+ 添加网盘链接/附件

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

易百纳技术社区