yike

yike

1个粉丝

109

问答

0

专栏

45

资料

yike  发布于  2008-12-29 17:40:53
采纳率 0%
109个问答
2603

手写软件设计技术2

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

[hide]
/**///////////////////////////////////////////////////////////////////////
// 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_FROM_LIB同一时间只能定义一个.如果两个都定义,毫无疑问,出错!^_^
  
  最后,用伪代码做范例说明如何使用该封装类,以此做本章结尾:
        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)
举报反馈

举报类型

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

详细说明

易百纳技术社区