基于Visual C++2010与windows SDK fo windows7开发windows7平台的tabletpc应用(2)-汉字文档手写轨迹输入多语言识别

大家先看看流程与效果,然后我来讲解代码,

1.VS2010帅气的启动画面

2.VS2010的工程画面

3。程序最终生成画面

4.程序启动画面

5 程序运行画面

6.程序枚举所有的语言识别手写识别器

7 英文识别范例

8。韩文识别范例

9.中文识别范例

10.线条式文档

11.格子式样文档

12.书写向导模式

13.tablet pc的笔势

核心代码讲解如下

核心头文件代码讲解

#pragma once class CAdvRecoApp : public CWindowImpl<CAdvRecoApp>, public IInkCollectorEventsImpl<CAdvRecoApp>, public IInkRecognitionEventsImpl<CAdvRecoApp> { public: // 常量 enum { // 子指数 mc_iSubmenuRecognizers = 1, mc_iSubmenuInputScopes = 2, mc_iSubmenuGuides = 3, mc_iSubmenuModes = 4, // child windows IDs mc_iInputWndId = 1, mc_iOutputWndId = 2, mc_iStatusWndId = 3, mc_iSSGestLVId = 4, mc_iMSGestLVId = 5, // 识别指南框数据 mc_iNumRowsCols = 100, mc_iGuideColWidth = 100, mc_iGuideRowHeight = 100, mc_cxBoxMargin = 4, mc_cyBoxMargin = 4, // t宽度 mc_cxGestLVWidth = 160, // 格子数目 mc_cNumSSGestures = 36, // single stroke gestures mc_cNumMSGestures = 6, // multi-stroke gestures // 笔的笔记宽度 mc_iPenWidth = 5 }; // COM指针,手写引擎的对象指针 CComPtr<IInkCollector> m_spIInkCollector; CComPtr<IInkRenderer> m_spIInkRenderer; CComPtr<IInkDisp> m_spIInkDisp; CComPtr<IInkStrokes> m_spIInkStrokes; CComPtr<IInkRecognizerContext> m_spIInkRecoContext; CComPtr<IInkRecognizers> m_spIInkRecognizers; CComPtr<IInkRecognizerGuide> m_spIInkRecoGuide; // 子窗口 CInkInputWnd m_wndInput; CRecoOutputWnd m_wndResults; HWND m_hwndStatusBar; HWND m_hwndSSGestLV; HWND m_hwndMSGestLV; // 定义数据变量 UINT m_nCmdRecognizer; UINT m_nCmdInputScope; UINT m_nCmdGuide; UINT m_nCmdMode; CComBSTR m_bstrCurRecoName; bool m_bCoerceInputScope; SIZE m_szGuideBox; bool m_bAllSSGestures; bool m_bAllMSGestures; // 创建 static int Run(int nCmdShow); //程序启动 CAdvRecoApp() : m_hwndStatusBar(NULL), m_hwndSSGestLV(NULL), m_hwndMSGestLV(NULL), m_bCoerceInputScope(false), m_nCmdGuide(0), m_nCmdInputScope(0), m_nCmdRecognizer(0), m_nCmdMode(0), m_bAllSSGestures(true), m_bAllMSGestures(true) { m_szGuideBox.cx = m_szGuideBox.cy = 0; } // 所有程序方法 HMENU LoadMenu(); bool CreateChildWindows(); void UpdateLayout(); void UpdateMenuRadioItems(UINT iSubMenu, UINT idCheck, UINT idUncheck); void UpdateInputScopeMenu(); void UpdateStatusBar(); bool UseRecognizer(IInkRecognizer* pIInkRecognizer); bool GetGestureName(InkApplicationGesture idGesture, UINT& idGestureName); void PresetGestures(); DECLARE_WND_CLASS_EX(NULL, 0, -1) BEGIN_MSG_MAP(CAdvRecoApp) MESSAGE_HANDLER(WM_CREATE, OnCreate) MESSAGE_HANDLER(WM_DESTROY, OnDestroy) MESSAGE_HANDLER(WM_SIZE, OnSize) COMMAND_ID_HANDLER(ID_RECOGNIZER_DEFAULT, OnRecognizer) COMMAND_RANGE_HANDLER(ID_RECOGNIZER_FIRST, ID_RECOGNIZER_LAST, OnRecognizer) COMMAND_ID_HANDLER(ID_INPUTSCOPE_COERCE, OnInputScopeCoerce) COMMAND_RANGE_HANDLER(ID_INPUTSCOPE_FIRST, ID_INPUTSCOPE_LAST, OnInputScope) COMMAND_ID_HANDLER(ID_GUIDE_NONE, OnGuide) COMMAND_ID_HANDLER(ID_GUIDE_LINES, OnGuide) COMMAND_ID_HANDLER(ID_GUIDE_BOXES, OnGuide) COMMAND_ID_HANDLER(ID_MODE_INK, OnMode) COMMAND_ID_HANDLER(ID_MODE_INK_AND_GESTURES, OnMode) COMMAND_ID_HANDLER(ID_MODE_GESTURES, OnMode) COMMAND_ID_HANDLER(ID_RECOGNIZE, OnRecognize) COMMAND_ID_HANDLER(ID_CLEAR, OnClear) COMMAND_ID_HANDLER(ID_EXIT, OnExit) NOTIFY_HANDLER(mc_iSSGestLVId, LVN_COLUMNCLICK, OnLVColumnClick) NOTIFY_HANDLER(mc_iMSGestLVId, LVN_COLUMNCLICK, OnLVColumnClick) NOTIFY_HANDLER(mc_iSSGestLVId, LVN_ITEMCHANGING, OnLVItemChanging) NOTIFY_HANDLER(mc_iMSGestLVId, LVN_ITEMCHANGING, OnLVItemChanging) END_MSG_MAP() public: // 消息函数 LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnSetFocus(UINT, WPARAM, LPARAM, BOOL& bHandled); LRESULT OnSize(UINT, WPARAM, LPARAM, BOOL& bHandled); LRESULT OnLVColumnClick(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); LRESULT OnLVItemChanging(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); // 命令句柄 LRESULT OnRecognizer(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); LRESULT OnInputScopeCoerce(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); LRESULT OnInputScope(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); LRESULT OnGuide(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); LRESULT OnMode(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); LRESULT OnRecognize(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); LRESULT OnClear(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); LRESULT OnExit(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); // 笔迹句柄 HRESULT OnStroke(IInkCursor* pIInkCursor, IInkStrokeDisp* pIInkStroke, VARIANT_BOOL* pbCancel); HRESULT OnGesture(IInkCursor* pIInkCursor, IInkStrokes* pIInkStrokes, VARIANT vGestures, VARIANT_BOOL* pbCancel); //识别器句柄 HRESULT OnRecognitionWithAlternates(IInkRecognitionResult* pIInkRecoResult, VARIANT vCustomParam, InkRecognitionStatus RecognitionStatus); };

核心源文件的代码讲解

#ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0500 #endif #include <windows.h> #include <commctrl.h> // com指针所需头文件 #ifndef ListView_SetCheckState #define ListView_SetCheckState(hwndLV, i, fCheck) / ListView_SetItemState(hwndLV, i, INDEXTOSTATEIMAGEMASK((fCheck ? 2 : 1)), LVIS_STATEIMAGEMASK) #endif #ifndef ListView_GetCheckState #define ListView_GetCheckState(hwndLV, i) / ((((UINT)(SNDMSG((hwndLV), LVM_GETITEMSTATE, (WPARAM)(i), LVIS_STATEIMAGEMASK))) >> 12) -1) #endif #ifndef MIIM_STRING #define MIIM_STRING 0x00000040 #endif #ifndef MIIM_FTYPE #define MIIM_FTYPE 0x00000100 #endif // 定义数组容纳笔势 #define countof(array) (sizeof(array)/sizeof(array[0])) #include <atlbase.h> / CComModule _Module; #include <atlwin.h> #include <atlcom.h> // Tablet PC 头文件 #include <msinkaut.h> #include <msinkaut_i.c> #include <tpcerror.h> #include "resource.h" #include "EventSinks.h" #include "ChildWnds.h" #include "AdvReco.h" //定义初始化变量 const LPOLESTR gc_pwsInputScopes[] = { L"(!IS_DEFAULT)", L"(!IS_URL)", L"(!IS_FILE_FULLFILEPATH)", L"(!IS_FILE_FILENAME)", L"(!IS_EMAIL_USERNAME)", L"(!IS_EMAIL_SMTPEMAILADDRESS)", L"(!IS_LOGINNAME)", L"(!IS_PERSONALNAME_FULLNAME)", L"(!IS_PERSONALNAME_PREFIX)", L"(!IS_PERSONALNAME_GIVENNAME)", L"(!IS_PERSONALNAME_MIDDLENAME)", L"(!IS_PERSONALNAME_SURNAME)", L"(!IS_PERSONALNAME_SUFFIX)", L"(!IS_ADDRESS_FULLPOSTALADDRESS)", L"(!IS_ADDRESS_POSTALCODE)", L"(!IS_ADDRESS_STREET)", L"(!IS_ADDRESS_STATEORPROVINCE)", L"(!IS_ADDRESS_CITY)", L"(!IS_ADDRESS_COUNTRYNAME)", L"(!IS_ADDRESS_COUNTRYSHORTNAME)", L"(!IS_CURRENCY_AMOUNTANDSYMBOL)", L"(!IS_CURRENCY_AMOUNT)", L"(!IS_DATE_FULLDATE)", L"(!IS_DATE_MONTH)", L"(!IS_DATE_DAY)", L"(!IS_DATE_YEAR)", L"(!IS_DATE_MONTHNAME)", L"(!IS_DATE_DAYNAME)", L"(!IS_DIGITS)", L"(!IS_NUMBER)", L"(!IS_ONECHAR)", L"(!IS_TELEPHONE_FULLTELEPHONENUMBER)", L"(!IS_TELEPHONE_COUNTRYCODE)", L"(!IS_TELEPHONE_AREACODE)", L"(!IS_TELEPHONE_LOCALNUMBER)", L"(!IS_TIME_FULLTIME)", L"(!IS_TIME_HOUR)", L"(!IS_TIME_MINORSEC)", L"((0|1|2|3|4|5|6|7|8|9) ?(0|1|2|3|4|5|6|7|8|9) ?(0|1|2|3|4|5|6|7|8|9) ?-? ?)?(0|1|2|3|4|5|6|7|8|9) ?(0|1|2|3|4|5|6|7|8|9) ?(0|1|2|3|4|5|6|7|8|9) ?-? ?(0|1|2|3|4|5|6|7|8|9) ?(0|1|2|3|4|5|6|7|8|9) ?(0|1|2|3|4|5|6|7|8|9) ?(0|1|2|3|4|5|6|7|8|9)", L"(!IS_PERSONALNAME_FULLNAME)|((!IS_PERSONALNAME_PREFIX)? +(!IS_PERSONALNAME_GIVENNAME)+ +(!IS_PERSONALNAME_MIDDLENAME)* +(!IS_PERSONALNAME_SURNAME)+)", L"MN(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)(A|B)(!IS_DIGITS)(X|Y)((0|1)*)" }; const LONG gc_lMaxInputScopeMenuItemLength = 40; // 定义笔势常量 const InkApplicationGesture gc_igtSingleStrokeGestures[] = { IAG_Scratchout, IAG_Triangle, IAG_Square, IAG_Star, IAG_Check, IAG_Circle, IAG_DoubleCircle, IAG_Curlicue, IAG_DoubleCurlicue, IAG_SemiCircleLeft, IAG_SemiCircleRight, IAG_ChevronUp, IAG_ChevronDown, IAG_ChevronLeft, IAG_ChevronRight, IAG_Up, IAG_Down, IAG_Left, IAG_Right, IAG_UpDown, IAG_DownUp, IAG_LeftRight, IAG_RightLeft, IAG_UpLeftLong, IAG_UpRightLong, IAG_DownLeftLong, IAG_DownRightLong, IAG_UpLeft, IAG_UpRight, IAG_DownLeft, IAG_DownRight, IAG_LeftUp, IAG_LeftDown, IAG_RightUp, IAG_RightDown, IAG_Tap }; const UINT gc_nRecommendedForMixedMode[] = { 0 /*Scratchout*/, 3/*Star*/, 6/*Double Circle*/, 7 /*Curlicue*/, 8 /*Double Curlicue*/, 25 /*Down-Left Long*/ }; const InkApplicationGesture gc_igtMultiStrokeGestures[] = { IAG_ArrowUp, IAG_ArrowDown, IAG_ArrowLeft, IAG_ArrowRight, IAG_Exclamation, IAG_DoubleTap }; const _ATL_FUNC_INFO IInkRecognitionEventsImpl<CAdvRecoApp>::mc_AtlFuncInfo = {CC_STDCALL, VT_EMPTY, 3, {VT_UNKNOWN, VT_VARIANT, VT_I4}}; const _ATL_FUNC_INFO IInkCollectorEventsImpl<CAdvRecoApp>::mc_AtlFuncInfo[2] = { {CC_STDCALL, VT_EMPTY, 3, {VT_UNKNOWN, VT_UNKNOWN, VT_BOOL|VT_BYREF}}, {CC_STDCALL, VT_EMPTY, 4, {VT_UNKNOWN, VT_UNKNOWN, VT_VARIANT, VT_BOOL|VT_BYREF}} }; const TCHAR gc_szAppName[] = TEXT("CSDN专家尹成的程序,http://blog.csdn.net/yincheng01"); //程序初始化窗口 int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, // not used here LPSTR /*lpCmdLine*/, // not used here int nCmdShow ) { int iRet = 0; // 初始化COM if (S_OK == ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)) { _Module.Init(NULL, hInstance); // 注册空间窗口 INITCOMMONCONTROLSEX icc; icc.dwSize = sizeof(icc); icc.dwICC = ICC_LISTVIEW_CLASSES | ICC_BAR_CLASSES; if (TRUE == ::InitCommonControlsEx(&icc)) { iRet = CAdvRecoApp::Run(nCmdShow); } else { ::MessageBox(NULL, TEXT("Error."), gc_szAppName, MB_ICONERROR | MB_OK); } _Module.Term(); ::CoUninitialize(); } return iRet; } //程序启动窗口 int CAdvRecoApp::Run( int nCmdShow ) { CAdvRecoApp theApp; HMENU hMenu = theApp.LoadMenu(); if (NULL == hMenu) return 0; int iRet; WNDCLASSEX& wc = CAdvRecoApp::GetWndClassInfo().m_wc; wc.hIcon = wc.hIconSm = ::LoadIcon(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_APPICON)); if (theApp.Create(NULL, CWindow::rcDefault, gc_szAppName, WS_OVERLAPPEDWINDOW, 0, (UINT)hMenu) != NULL) { theApp.SendMessage(WM_COMMAND, ID_GUIDE_NONE); //创建程序初始化消息 theApp.SendMessage(WM_COMMAND, ID_INPUTSCOPE_FIRST); // 创建默认识别器 theApp.SendMessage(WM_COMMAND, ID_RECOGNIZER_DEFAULT); // 设置收集数据识别器 theApp.SendMessage(WM_COMMAND, ID_MODE_INK); theApp.ShowWindow(nCmdShow); theApp.UpdateWindow(); // 开始消息循环 MSG msg; while (::GetMessage(&msg, NULL, 0, 0) > 0) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } iRet = msg.wParam; } else { ::MessageBox(NULL, TEXT("Error "), gc_szAppName, MB_ICONERROR | MB_OK); ::DestroyMenu(hMenu); iRet = 0; } return iRet; } // Window message 传递 LRESULT CAdvRecoApp::OnCreate( UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/ ) { if (false == CreateChildWindows()) return -1; HRESULT hr; //初始化com指针CLSID_InkCollector hr = m_spIInkCollector.CoCreateInstance(CLSID_InkCollector); if (FAILED(hr)) return -1; //初始化com指针m_spIInkDisp hr = m_spIInkCollector->get_Ink(&m_spIInkDisp); if (FAILED(hr)) return -1; //初始化com指针m_spIInkStrokes hr = m_spIInkDisp->get_Strokes(&m_spIInkStrokes); if (FAILED(hr)) return -1; //挂接笔迹事件 hr = IInkCollectorEventsImpl<CAdvRecoApp>::DispEventAdvise(m_spIInkCollector); if (FAILED(hr)) return -1; // 设置笔势 PresetGestures(); // 启动书写 hr = m_spIInkCollector->put_hWnd((long)m_wndInput.m_hWnd); if (FAILED(hr)) return -1; hr = m_spIInkCollector->put_Enabled(VARIANT_TRUE); if (FAILED(hr)) return -1; // 创建识别器向导 if (SUCCEEDED(m_spIInkRecoGuide.CoCreateInstance(CLSID_InkRecognizerGuide))) { _InkRecoGuide irg; irg.midline = -1; // 不用格子 irg.cRows = irg.cColumns = 0; // 不用划线 ::SetRect(&irg.rectWritingBox, 0, 0, mc_iGuideColWidth, mc_iGuideRowHeight); // M创建书写区域 irg.rectDrawnBox = irg.rectWritingBox; ::InflateRect(&irg.rectDrawnBox, -mc_cxBoxMargin, -mc_cyBoxMargin); m_wndInput.SetGuide(irg); // 收集笔迹区域 hr = m_spIInkCollector->get_Renderer(&m_spIInkRenderer); if (SUCCEEDED(hr)) { HDC hdc = m_wndInput.GetDC(); if (NULL != hdc) { // 转换笔迹 m_spIInkRenderer->PixelToInkSpace((long)hdc, &irg.rectWritingBox.left, &irg.rectWritingBox.top); m_spIInkRenderer->PixelToInkSpace((long)hdc, &irg.rectWritingBox.right, &irg.rectWritingBox.bottom); m_spIInkRenderer->PixelToInkSpace((long)hdc, &irg.rectDrawnBox.left, &irg.rectDrawnBox.top); m_spIInkRenderer->PixelToInkSpace((long)hdc, &irg.rectDrawnBox.right, &irg.rectDrawnBox.bottom); hr = m_spIInkRecoGuide->put_GuideData(irg); ReleaseDC(hdc); } else { hr = E_FAIL; } } if (FAILED(hr)) { m_spIInkRecoGuide.Release(); } } return 0; } //窗口毁灭,删除所有对象 LRESULT CAdvRecoApp::OnDestroy( UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/ ) { if (m_spIInkCollector != NULL) { IInkCollectorEventsImpl<CAdvRecoApp>::DispEventUnadvise(m_spIInkCollector); m_spIInkCollector->put_Enabled(VARIANT_FALSE); m_spIInkCollector.Release(); } if (m_spIInkRecoContext != NULL) { m_spIInkRecoContext->EndInkInput(); IInkRecognitionEventsImpl<CAdvRecoApp>::DispEventUnadvise(m_spIInkRecoContext); m_spIInkRecoContext.Release(); } m_spIInkRecoGuide.Release(); m_spIInkStrokes.Release(); m_spIInkRecognizers.Release(); ::PostQuitMessage(0); return 0; } //大小改变 LRESULT CAdvRecoApp::OnSize( UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/ ) { if (wParam != SIZE_MINIMIZED) { UpdateLayout(); } return 0; } // InkCollector句柄指针事件 HRESULT CAdvRecoApp::OnStroke( IInkCursor* /*pIInkCursor*/, IInkStrokeDisp* pIInkStroke, VARIANT_BOOL* /* pbCancel */ ) { if (NULL == pIInkStroke) return E_INVALIDARG; if (m_spIInkStrokes == NULL) return S_OK; HRESULT hr = m_spIInkStrokes->Add(pIInkStroke); if (SUCCEEDED(hr) && m_spIInkRecoContext != NULL) { m_spIInkRecoContext->StopBackgroundRecognition(); CComVariant vCustomData; //更新识别结果 m_spIInkRecoContext->BackgroundRecognizeWithAlternates(vCustomData); } return hr; } //笔势事件 HRESULT CAdvRecoApp::OnGesture( IInkCursor* /*pIInkCursor*/, IInkStrokes* pInkStrokes, VARIANT vGestures, VARIANT_BOOL* pbCancel ) { if (((VT_ARRAY | VT_DISPATCH) != vGestures.vt) || (NULL == vGestures.parray)) return E_INVALIDARG; if (0 == vGestures.parray->rgsabound->cElements) return E_INVALIDARG; / /数组中的手势应该是排序的承认 / /置信水平。此示例拿起最高之一。 / /注意:当在InkAndGesture收集模式,除了预期的手势 / /应用程序也有可能是带着身份证IAG_NoGesture手势对象 / /此应用程序时,如果取消与ISG_NoGesture对象 / /最高水平的信心数组(第一项)。 InkApplicationGesture idGesture = IAG_NoGesture; IDispatch** ppIDispatch; HRESULT hr = ::SafeArrayAccessData(vGestures.parray, (void HUGEP**)&ppIDispatch); if (SUCCEEDED(hr)) { CComQIPtr<IInkGesture> spIInkGesture(ppIDispatch[0]); if (spIInkGesture != NULL) { hr = spIInkGesture->get_Id(&idGesture); } ::SafeArrayUnaccessData(vGestures.parray); } / /加载资源字符串表的姿态名称 UINT idGestureName; bool bAccepted; // will be true, if the gesture is known to this application if (IAG_NoGesture != idGesture) { bAccepted = GetGestureName(idGesture, idGestureName); } else { bAccepted = false; idGestureName = 0; } //如果当前的收集模式ICM_GestureOnly或者如果我们接受 //的姿态,手势的中风将被删除从墨迹对象, //因此,窗口需要在招'区更新。 if (ID_MODE_GESTURES == m_nCmdMode || true == bAccepted) { // Get the rectangle to update. RECT rc; CComPtr<IInkRectangle> spIInkRect; if (m_spIInkRenderer != NULL && pInkStrokes != NULL && SUCCEEDED(pInkStrokes->GetBoundingBox(IBBM_Default, &spIInkRect)) && SUCCEEDED(spIInkRect->GetRectangle(&rc.top, &rc.left, &rc.bottom, &rc.right))) { HDC hdc = m_wndInput.GetDC(); if (NULL != hdc) { if (FAILED(m_spIInkRenderer->InkSpaceToPixel((long)hdc, &rc.left, &rc.top)) || FAILED(m_spIInkRenderer->InkSpaceToPixel((long)hdc, &rc.right, &rc.bottom))) { m_wndInput.GetClientRect(&rc); } ReleaseDC(hdc); } else { m_wndInput.GetClientRect(&rc); } } else { m_wndInput.GetClientRect(&rc); } m_wndInput.InvalidateRect(&rc); } else // if something's failed, { *pbCancel = VARIANT_TRUE; idGestureName = IDS_GESTURE_UNKNOWN; } m_wndResults.SetGestureName(idGestureName); m_wndResults.Invalidate(); return hr; } // Recognition event handlers 识别器事件 HRESULT CAdvRecoApp::OnRecognitionWithAlternates( IInkRecognitionResult* pIInkRecoResult, VARIANT /*vCustomParam*/, InkRecognitionStatus /*RecognitionStatus*/ ) { if (NULL == pIInkRecoResult) return E_INVALIDARG; m_wndResults.ResetResults(); // Get the best lCount results HRESULT hr; CComPtr<IInkRecognitionAlternates> spIInkRecoAlternates; hr = pIInkRecoResult->AlternatesFromSelection( 0, -1, CRecoOutputWnd::mc_iNumResults, &spIInkRecoAlternates ); LONG lCount = 0; if (SUCCEEDED(hr) && SUCCEEDED(spIInkRecoAlternates->get_Count(&lCount))) { IInkRecognitionAlternate* pIInkRecoAlternate = NULL; for (LONG iItem = 0; (iItem < lCount) && (iItem < CRecoOutputWnd::mc_iNumResults); iItem++) { if (SUCCEEDED(spIInkRecoAlternates->Item(iItem, &pIInkRecoAlternate))) { BSTR bstr = NULL; if (SUCCEEDED(pIInkRecoAlternate->get_String(&bstr))) { m_wndResults.m_bstrResults[iItem].Attach(bstr); } pIInkRecoAlternate->Release(); } } } // Update the output window with the new results m_wndResults.Invalidate(); return S_OK; } //识别结果获取 LRESULT CAdvRecoApp::OnRecognizer( WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/ ) { if (m_spIInkRecognizers == NULL || wID == m_nCmdRecognizer) return 0; HRESULT hr; CComPtr<IInkRecognizer> spIInkRecognizer; if (ID_RECOGNIZER_DEFAULT == wID) { hr = m_spIInkRecognizers->GetDefaultRecognizer(0, &spIInkRecognizer);//获取默认识别器设置之 } else { hr = m_spIInkRecognizers->Item(wID - ID_RECOGNIZER_FIRST, &spIInkRecognizer);//否则获取第一个识别器设置之 } if (SUCCEEDED(hr) && UseRecognizer(spIInkRecognizer)) { UpdateMenuRadioItems(mc_iSubmenuRecognizers, wID, m_nCmdRecognizer); m_bstrCurRecoName.Empty(); spIInkRecognizer->get_Name(&m_bstrCurRecoName); UpdateStatusBar(); m_nCmdRecognizer = wID; } return 0; } //输入获取 LRESULT CAdvRecoApp::OnInputScopeCoerce( WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/ ) { if (m_spIInkRecoContext == NULL ) return 0; if (m_spIInkStrokes != NULL) { m_spIInkRecoContext->putref_Strokes(NULL); } if (FAILED(m_spIInkRecoContext->put_RecognitionFlags (m_bCoerceInputScope?IRM_None:IRM_Coerce))) { MessageBox(TEXT("获取结果失败!"), gc_szAppName, MB_ICONERROR | MB_OK); // Re-attach the stroke collection to the context if (m_spIInkStrokes != NULL) { m_spIInkRecoContext->putref_Strokes(m_spIInkStrokes); } return 0; } m_bCoerceInputScope = !m_bCoerceInputScope; // 收集笔迹 if (m_spIInkStrokes != NULL) { m_spIInkRecoContext->putref_Strokes(m_spIInkStrokes); } // 更新识别结果 CComVariant vCustomData; // no custom data m_spIInkRecoContext->BackgroundRecognizeWithAlternates(vCustomData); // 更新菜单 HMENU hMenu = GetMenu(); if (NULL != hMenu) { HMENU hSubMenu = ::GetSubMenu(hMenu, mc_iSubmenuInputScopes); if (NULL != hSubMenu) { ::CheckMenuItem(hSubMenu, wID, MF_BYCOMMAND | (m_bCoerceInputScope ? MF_CHECKED : MF_UNCHECKED)); } } return 0; } LRESULT CAdvRecoApp::OnInputScope( WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/ ) { UINT iInputScope = wID - ID_INPUTSCOPE_FIRST; if (wID == m_nCmdInputScope || iInputScope >= countof(gc_pwsInputScopes)) return 0; if (m_spIInkRecoContext != NULL) { if (m_spIInkStrokes != NULL) { m_spIInkRecoContext->putref_Strokes(NULL); } CComBSTR bstrInputScope(gc_pwsInputScopes[iInputScope]); HRESULT hr = m_spIInkRecoContext->put_Factoid(bstrInputScope); if (m_spIInkStrokes != NULL) { m_spIInkRecoContext->putref_Strokes(m_spIInkStrokes); } if (SUCCEEDED(hr)) { CComVariant vCustomData; m_spIInkRecoContext->BackgroundRecognizeWithAlternates(vCustomData); } else if (TPC_E_INVALID_PROPERTY == hr) { return 0; } else { return 0; } } UpdateMenuRadioItems(mc_iSubmenuInputScopes, wID, m_nCmdInputScope); m_nCmdInputScope = wID; UpdateStatusBar(); return 0; } //识别向导 LRESULT CAdvRecoApp::OnGuide( WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/ ) { if (m_spIInkRecoGuide == NULL || wID == m_nCmdGuide) return 0; int cRows = 0, cColumns = 0; if (ID_GUIDE_LINES == wID || ID_GUIDE_BOXES == wID) { cRows = mc_iNumRowsCols; if (ID_GUIDE_BOXES == wID) { cColumns = mc_iNumRowsCols; } } if (SUCCEEDED(m_spIInkRecoGuide->put_Rows(cRows)) && SUCCEEDED(m_spIInkRecoGuide->put_Columns(cColumns))) { HRESULT hr = S_OK; if (m_spIInkRecoContext != NULL) { if (m_spIInkStrokes != NULL) { m_spIInkRecoContext->putref_Strokes(NULL); } hr = m_spIInkRecoContext->putref_Guide(m_spIInkRecoGuide); if (m_spIInkStrokes != NULL) { m_spIInkRecoContext->putref_Strokes(m_spIInkStrokes); } CComVariant vCustomData; m_spIInkRecoContext->BackgroundRecognizeWithAlternates(vCustomData); } if (SUCCEEDED(hr)) { m_wndInput.SetRowsCols(cRows, cColumns); UpdateMenuRadioItems(mc_iSubmenuGuides, wID, m_nCmdGuide); m_nCmdGuide = wID; } } return 0; } //变换模式 LRESULT CAdvRecoApp::OnMode( WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/ ) { if (wID == m_nCmdMode) return 0; InkCollectionMode icm; switch (wID) { default: return 0; case ID_MODE_INK: icm = ICM_InkOnly; break; case ID_MODE_INK_AND_GESTURES: icm = ICM_InkAndGesture; break; case ID_MODE_GESTURES: icm = ICM_GestureOnly; break; } if (m_spIInkCollector != NULL && SUCCEEDED(m_spIInkCollector->put_Enabled(VARIANT_FALSE))) { if (SUCCEEDED(m_spIInkCollector->put_CollectionMode(icm))) { UpdateMenuRadioItems(mc_iSubmenuModes, wID, m_nCmdMode); m_nCmdMode = wID; UpdateLayout(); } if (FAILED(m_spIInkCollector->put_Enabled(VARIANT_TRUE))) { MessageBox(TEXT("模式设置失败!"), gc_szAppName, MB_ICONERROR | MB_OK); } } return 0; } //识别 WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/ ) { if (m_spIInkRecoContext != NULL) { m_spIInkRecoContext->EndInkInput(); CComPtr<IInkRecognitionResult> spIInkRecoResult; InkRecognitionStatus ink_reco_status = IRS_NoError; if (SUCCEEDED(m_spIInkRecoContext->Recognize(&ink_reco_status, &spIInkRecoResult))) { CComVariant vCustomData; OnRecognitionWithAlternates(spIInkRecoResult, vCustomData, ink_reco_status); } else { MessageBox(TEXT("识别失败."), gc_szAppName, MB_ICONERROR | MB_OK); } if (m_spIInkStrokes != NULL) { if (FAILED(m_spIInkRecoContext->putref_Strokes(m_spIInkStrokes))) { MessageBox(TEXT("Failed to attach the stroke collection to the recognition context!"), gc_szAppName, MB_ICONERROR | MB_OK); } } } return 0; } LRESULT CAdvRecoApp::OnClear( WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/ ) { if (m_spIInkDisp != NULL) { m_spIInkDisp->DeleteStrokes(0); m_spIInkStrokes.Release(); CComVariant vt(0); if (FAILED(m_spIInkDisp->CreateStrokes(vt, &m_spIInkStrokes))) { MessageBox(TEXT("笔迹获取失败"), gc_szAppName, MB_ICONERROR | MB_OK); } if (m_spIInkRecoContext != NULL) { if (FAILED(m_spIInkRecoContext->putref_Strokes(m_spIInkStrokes))) { MessageBox(TEXT("收集数据失败"), gc_szAppName, MB_ICONERROR | MB_OK); } } } // 更新窗口 m_wndResults.ResetResults(); m_wndResults.Invalidate(); m_wndInput.Invalidate(); return 0; } //退出 LRESULT CAdvRecoApp::OnExit( WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/ ) { // Close the application window SendMessage(WM_CLOSE); return 0; } //获取识别器集合,获取笔势集合 HMENU CAdvRecoApp::LoadMenu() { HRESULT hr = S_OK; // 获取识别器 hr = m_spIInkRecognizers.CoCreateInstance(CLSID_InkRecognizers); if (FAILED(hr)) return NULL; // 获取识别器数目 LONG lCount = 0; hr = m_spIInkRecognizers->get_Count(&lCount); if (0 == lCount) { gc_szAppName, MB_ICONERROR | MB_OK); return NULL; } // 载入windows的菜单 HMENU hMenu = ::LoadMenu(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MENU)); if (NULL == hMenu) return NULL; // Not normal MENUITEMINFOW miinfo; memset(&miinfo, 0, sizeof(miinfo)); miinfo.cbSize = sizeof(miinfo); miinfo.fMask = MIIM_ID | MIIM_STATE | MIIM_FTYPE | MIIM_STRING; miinfo.fType = MFT_RADIOCHECK | MFT_STRING; // 获取所有识别器 HMENU hSubMenu = ::GetSubMenu(hMenu, mc_iSubmenuRecognizers); if (hSubMenu) { CComPtr<IInkRecognizer> spIInkRecognizer; miinfo.wID = ID_RECOGNIZER_FIRST; miinfo.fState = 0; for (LONG i = 0; i < lCount; i++, miinfo.wID++) { if (FAILED(m_spIInkRecognizers->Item(i, &spIInkRecognizer))) continue; CComVariant vLanguages; if (SUCCEEDED(spIInkRecognizer->get_Languages(&vLanguages))) { if ((VT_ARRAY == (VT_ARRAY & vLanguages.vt)) && (NULL != vLanguages.parray) && (0 < vLanguages.parray->rgsabound[0].cElements)) { CComBSTR bstrName; if (SUCCEEDED(spIInkRecognizer->get_Name(&bstrName))) { miinfo.dwTypeData = bstrName; ::InsertMenuItemW(hSubMenu, (UINT)-1, TRUE, &miinfo); } } spIInkRecognizer.Release(); } } } // 获取所有笔势集合 hSubMenu = ::GetSubMenu(hMenu, mc_iSubmenuInputScopes); if (hSubMenu) { miinfo.wID = ID_INPUTSCOPE_FIRST; miinfo.fState = 0; lCount = countof(gc_pwsInputScopes); for(LONG i = 0; i < lCount; i++, miinfo.wID++) { if (wcslen(gc_pwsInputScopes[i]) <= gc_lMaxInputScopeMenuItemLength) { miinfo.dwTypeData = gc_pwsInputScopes[i]; } else { CComBSTR bstrInputScope(gc_lMaxInputScopeMenuItemLength-3, gc_pwsInputScopes[i]); bstrInputScope += L"..."; miinfo.dwTypeData = bstrInputScope; } ::InsertMenuItemW(hSubMenu, (UINT)-1, TRUE, &miinfo); } } return hMenu; } //菜单消息处理 void CAdvRecoApp::UpdateInputScopeMenu() { HMENU hMenu = GetMenu(); if (NULL != hMenu) { HMENU hSubMenu = ::GetSubMenu(hMenu, mc_iSubmenuInputScopes); if (NULL != hSubMenu) { if (m_spIInkRecoContext != NULL) { CComBSTR bstrInputScope; if (FAILED(m_spIInkRecoContext->get_Factoid(&bstrInputScope))) { return; } if (m_spIInkStrokes != NULL) { m_spIInkRecoContext->putref_Strokes(NULL); } MENUITEMINFO miinfo; memset(&miinfo, 0, sizeof(miinfo)); miinfo.cbSize = sizeof(miinfo); miinfo.fMask = MIIM_STATE; miinfo.wID = ID_INPUTSCOPE_FIRST; for(LONG i = 0; i < countof(gc_pwsInputScopes); i++, miinfo.wID++) { CComBSTR bstrTestInputScope(gc_pwsInputScopes[i]); HRESULT hr = m_spIInkRecoContext->put_Factoid(bstrTestInputScope); if (FAILED(hr)) { miinfo.fState = MFS_DISABLED; } else { miinfo.fState = MFS_ENABLED; } ::SetMenuItemInfo(hSubMenu, miinfo.wID, FALSE, &miinfo); } if (FAILED(m_spIInkRecoContext->put_Factoid(bstrInputScope))) { } if (m_spIInkStrokes != NULL) { m_spIInkRecoContext->putref_Strokes(m_spIInkStrokes); } } } } } //更新信息 void CAdvRecoApp::UpdateMenuRadioItems( UINT iSubMenu, UINT idCheck, UINT idUncheck ) { // 更新菜单 HMENU hMenu = GetMenu(); if (NULL != hMenu) { HMENU hSubMenu = ::GetSubMenu(hMenu, iSubMenu); if (NULL != hSubMenu) { MENUITEMINFO miinfo; miinfo.cbSize = sizeof(miinfo); miinfo.fMask = MIIM_STATE | MIIM_FTYPE; ::GetMenuItemInfo(hSubMenu, idCheck, FALSE, &miinfo); miinfo.fType |= MFT_RADIOCHECK; miinfo.fState |= MFS_CHECKED; ::SetMenuItemInfo(hSubMenu, idCheck, FALSE, &miinfo); if (0 != idUncheck) { ::GetMenuItemInfo(hSubMenu, idUncheck, FALSE, &miinfo); miinfo.fType |= MFT_RADIOCHECK; miinfo.fState &= ~MFS_CHECKED; ::SetMenuItemInfo(hSubMenu, idUncheck, FALSE, &miinfo); } } } } //使用识别器识别 bool CAdvRecoApp::UseRecognizer( IInkRecognizer* pIInkRecognizer ) { if (NULL == pIInkRecognizer) return false; // 创建接口 CComPtr<IInkRecognizerContext> spNewContext; HCURSOR hCursor = ::SetCursor(::LoadCursor(NULL, IDC_WAIT)); if (m_spIInkRecoContext != NULL) { IInkRecognitionEventsImpl<CAdvRecoApp>::DispEventUnadvise(m_spIInkRecoContext); m_spIInkRecoContext->putref_Strokes(NULL); m_spIInkRecoContext.Release(); } hr = IInkRecognitionEventsImpl<CAdvRecoApp>::DispEventAdvise(spNewContext); InkRecognizerCapabilities dwCapabilities; if (FAILED(pIInkRecognizer->get_Capabilities(&dwCapabilities))) { dwCapabilities = IRC_DontCare; } const UINT nGuideCmds[] = {ID_GUIDE_BOXES, ID_GUIDE_LINES, ID_GUIDE_NONE}; const UINT nGuideFlags[] = {IRC_BoxedInput, IRC_LinedInput, IRC_FreeInput}; HMENU hMenu = GetMenu(); HMENU hSubMenu = hMenu ? ::GetSubMenu(hMenu, mc_iSubmenuGuides) : NULL; UINT nCmdGuid = 0; for (ULONG i = 0; i < countof(nGuideCmds) && i < countof(nGuideFlags); i++) { UINT nFlags; if (m_spIInkRecoGuide != NULL && (((nGuideFlags[i] & dwCapabilities) == nGuideFlags[i]) || ((IRC_DontCare & dwCapabilities) == IRC_DontCare))) { nFlags = MF_BYCOMMAND | MF_ENABLED; if ((0 == nCmdGuid) || (nGuideCmds[i] == m_nCmdGuide)) { nCmdGuid = nGuideCmds[i]; } } else { nFlags = MF_BYCOMMAND | MF_GRAYED; } // 更新菜单 if (NULL != hSubMenu) { ::EnableMenuItem(hSubMenu, nGuideCmds[i], nFlags); } } // 转换识别器 if (m_nCmdGuide != nCmdGuid) { SendMessage(WM_COMMAND, nCmdGuid); } // 设置识别结果在识别器具 // 设置向导 if (m_spIInkRecoGuide != NULL && 0 != m_nCmdGuide) { if (FAILED(spNewContext->putref_Guide(m_spIInkRecoGuide))) { } } m_nCmdInputScope = -1; m_bCoerceInputScope = false; CComBSTR bstrFactoid(FACTOID_DEFAULT); if (FAILED(spNewContext->put_Factoid(bstrFactoid))) { MessageBox(TEXT("Failed to set factoid to the new recognition context!"), gc_szAppName, MB_ICONERROR | MB_OK); } hr = spNewContext->putref_Strokes(m_spIInkStrokes); m_spIInkRecoContext.Attach(spNewContext.Detach()); UpdateMenuRadioItems(mc_iSubmenuInputScopes, ID_INPUTSCOPE_FIRST, m_nCmdInputScope); UpdateInputScopeMenu(); hSubMenu = hMenu ? ::GetSubMenu(hMenu, mc_iSubmenuInputScopes) : NULL; if (NULL != hSubMenu) { ::CheckMenuItem(hSubMenu, ID_INPUTSCOPE_COERCE, MF_BYCOMMAND | MF_UNCHECKED); } LANGID wLandId = ::GetUserDefaultLangID(); CComVariant vLangIDs; if (SUCCEEDED(pIInkRecognizer->get_Languages(&vLangIDs)) && NULL != vLangIDs.parray) { WORD* pwLIDs; if (SUCCEEDED(::SafeArrayAccessData(vLangIDs.parray, (void HUGEP**)&pwLIDs))) { wLandId = pwLIDs[0]; ::SafeArrayUnaccessData(vLangIDs.parray); } } m_wndResults.ResetResults(); m_wndResults.Invalidate(); CComVariant vCustomData; m_spIInkRecoContext->BackgroundRecognizeWithAlternates(vCustomData); ::SetCursor(hCursor); return true; } LRESULT CAdvRecoApp::OnLVColumnClick( int idCtrl, LPNMHDR /*pnmh*/, BOOL& bHandled ) { if (mc_iSSGestLVId == idCtrl) { m_bAllSSGestures = !m_bAllSSGestures; ListView_SetCheckState(m_hwndSSGestLV, -1, m_bAllSSGestures); } else if (mc_iMSGestLVId == idCtrl) { m_bAllMSGestures = !m_bAllMSGestures; ListView_SetCheckState(m_hwndMSGestLV, -1, m_bAllMSGestures); } else { bHandled = FALSE; } return 0; } LRESULT CAdvRecoApp::OnLVItemChanging( int idCtrl, LPNMHDR pnmh, BOOL& /*bHandled*/ ) { if (m_spIInkCollector == NULL) return FALSE; LPNMLISTVIEW pnmv = (LPNMLISTVIEW)pnmh; LRESULT lRet; if (LVIF_STATE == pnmv->uChanged && 0 != (LVIS_STATEIMAGEMASK & pnmv->uNewState)) { lRet = TRUE; BOOL bChecked = ((LVIS_STATEIMAGEMASK & pnmv->uNewState) >> 12) == 2; InkApplicationGesture igtGesture = IAG_NoGesture; if (mc_iSSGestLVId == idCtrl) { if (pnmv->iItem >= 0 && pnmv->iItem < countof(gc_igtSingleStrokeGestures)) igtGesture = gc_igtSingleStrokeGestures[pnmv->iItem]; } else if (mc_iMSGestLVId == idCtrl) { if (pnmv->iItem >= 0 && pnmv->iItem < countof(gc_igtMultiStrokeGestures)) igtGesture = gc_igtMultiStrokeGestures[pnmv->iItem]; } if (IAG_NoGesture != igtGesture && SUCCEEDED( m_spIInkCollector->SetGestureStatus(igtGesture, bChecked ? VARIANT_TRUE : VARIANT_FALSE))) { lRet = FALSE; } } else { lRet = FALSE; } return lRet; } bool CAdvRecoApp::CreateChildWindows() { if ((m_wndInput.Create(m_hWnd, CWindow::rcDefault, NULL, WS_CHILD, WS_EX_CLIENTEDGE, (UINT)mc_iInputWndId) == NULL) || (m_wndResults.Create(m_hWnd, CWindow::rcDefault, NULL, WS_CHILD, WS_EX_CLIENTEDGE, (UINT)mc_iOutputWndId) == NULL)) { return false; } HINSTANCE hInst = _Module.GetResourceInstance(); // 创建控件于子窗口 m_hwndSSGestLV = ::CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, NULL, WS_VISIBLE | WS_CHILD | WS_BORDER | LVS_REPORT, 0, 0, 1, 1, m_hWnd, (HMENU)mc_iSSGestLVId, _Module.GetModuleInstance(), NULL); if (NULL == m_hwndSSGestLV) return false; ListView_SetExtendedListViewStyleEx(m_hwndSSGestLV, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES); LV_COLUMN lvC; lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvC.fmt = LVCFMT_LEFT; lvC.iSubItem = 0; lvC.cx = mc_cxGestLVWidth - 22; lvC.pszText = TEXT("Single Stroke Gestures"); if (-1 == ListView_InsertColumn(m_hwndSSGestLV, lvC.iSubItem, &lvC)) return false; TCHAR szText[100]; LV_ITEM lvItem; lvItem.mask = LVIF_TEXT /*| LVIF_IMAGE*/ | LVIF_STATE; lvItem.state = 0; lvItem.stateMask = 0; lvItem.pszText = szText; lvItem.iSubItem = 0; for (ULONG i = 0; i < mc_cNumSSGestures; i++) { lvItem.iItem = i; ::LoadString(hInst, IDS_SSGESTURE_FIRST + i, szText, countof(szText)); if (-1 == ListView_InsertItem(m_hwndSSGestLV, &lvItem)) return false; } m_hwndMSGestLV = ::CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, NULL, WS_VISIBLE | WS_CHILD | WS_BORDER | LVS_REPORT, 0, 0, 1, 1, m_hWnd, (HMENU)mc_iMSGestLVId, _Module.GetModuleInstance(), NULL); if (NULL == m_hwndMSGestLV) return false; ListView_SetExtendedListViewStyleEx(m_hwndMSGestLV, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES); lvC.pszText = TEXT("Multiple Stroke Gestures"); ListView_InsertColumn(m_hwndMSGestLV, lvC.iSubItem, &lvC); for (ULONG i = 0; i < mc_cNumMSGestures; i++) { lvItem.iItem = i; ::LoadString(hInst, IDS_MSGESTURE_FIRST + i, szText, countof(szText)); if (-1 == ListView_InsertItem(m_hwndMSGestLV, &lvItem)) return false; } m_hwndStatusBar = ::CreateStatusWindow( WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN|WS_CLIPSIBLINGS|SBARS_SIZEGRIP, NULL, m_hWnd, (UINT)mc_iStatusWndId); if (NULL != m_hwndStatusBar) { ::SendMessage(m_hwndStatusBar, WM_SETFONT, (LPARAM)::GetStockObject(DEFAULT_GUI_FONT), FALSE); } UpdateLayout(); return true; } void CAdvRecoApp::UpdateLayout() { RECT rect; GetClientRect(&rect); if (::IsWindow(m_hwndStatusBar) && ((DWORD)::GetWindowLong(m_hwndStatusBar, GWL_STYLE) & WS_VISIBLE)) { ::SendMessage(m_hwndStatusBar, WM_SIZE, 0, 0); RECT rectStatusBar; ::GetWindowRect(m_hwndStatusBar, &rectStatusBar); if (rect.bottom > rectStatusBar.bottom - rectStatusBar.top) { rect.bottom -= rectStatusBar.bottom - rectStatusBar.top; } else { rect.bottom = 0; } } if (::IsWindow(m_hwndSSGestLV) && ::IsWindow(m_hwndMSGestLV)) { if (ID_MODE_INK != m_nCmdMode) { RECT rcGest = rect; if (rcGest.right < mc_cxGestLVWidth) { rcGest.left = 0; } else { rcGest.left = rcGest.right - mc_cxGestLVWidth; } rect.right = rcGest.left; if (ID_MODE_GESTURES == m_nCmdMode) { int iHeight; RECT rcItem; if (TRUE == ListView_GetItemRect(m_hwndMSGestLV, 0, &rcItem, LVIR_BOUNDS)) { iHeight = rcItem.top + (rcItem.bottom - rcItem.top) * (countof(gc_igtMultiStrokeGestures) + 1); } else { iHeight = (rcGest.bottom - rcGest.top) / 3; } ::SetWindowPos(m_hwndMSGestLV, NULL, rcGest.left, rcGest.bottom - iHeight, rcGest.right - rcGest.left, iHeight, SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW); rcGest.bottom -= iHeight; } else if (WS_VISIBLE == (((DWORD)::GetWindowLong(m_hwndMSGestLV, GWL_STYLE)) & WS_VISIBLE)) { ::ShowWindow(m_hwndMSGestLV, SW_HIDE); } ::SetWindowPos(m_hwndSSGestLV, NULL, rcGest.left, rcGest.top, rcGest.right - rcGest.left, rcGest.bottom - rcGest.top, SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW); } else { if (WS_VISIBLE == (((DWORD)::GetWindowLong(m_hwndSSGestLV, GWL_STYLE)) & WS_VISIBLE)) { ::ShowWindow(m_hwndSSGestLV, SW_HIDE); } if (WS_VISIBLE == (((DWORD)::GetWindowLong(m_hwndMSGestLV, GWL_STYLE)) & WS_VISIBLE)) { ::ShowWindow(m_hwndMSGestLV, SW_HIDE); } } } if (::IsWindow(m_wndResults.m_hWnd)) { int cyResultsWnd = m_wndResults.GetBestHeight(); if (cyResultsWnd > rect.bottom) { cyResultsWnd = rect.bottom; } ::SetWindowPos(m_wndResults.m_hWnd, NULL, rect.left, rect.bottom - cyResultsWnd, rect.right - rect.left, cyResultsWnd - rect.top, SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW); rect.bottom -= cyResultsWnd; } if (::IsWindow(m_wndInput.m_hWnd)) { ::SetWindowPos(m_wndInput.m_hWnd, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW); } } void CAdvRecoApp::UpdateStatusBar() { if (NULL == m_hwndStatusBar) return; UINT iInputScope = m_nCmdInputScope - ID_INPUTSCOPE_FIRST; if (iInputScope >= sizeof(gc_pwsInputScopes)/sizeof(gc_pwsInputScopes[0])) { iInputScope = 0; } CComBSTR bstrStatus(m_bstrCurRecoName); if (m_nCmdInputScope != -1) { bstrStatus += L"; Input Scope: "; bstrStatus += gc_pwsInputScopes[iInputScope]; } ::SendMessage(m_hwndStatusBar, SB_SETTEXTW, NULL, (LPARAM)bstrStatus.m_str); } bool CAdvRecoApp::GetGestureName( InkApplicationGesture igtGesture, UINT& idGestureName ) { idGestureName = IDS_GESTURE_UNKNOWN; if (ID_MODE_INK == m_nCmdMode) return false; ULONG iCount = countof(gc_igtSingleStrokeGestures); ULONG i; for (i = 0; i < iCount; i++) { if (gc_igtSingleStrokeGestures[i] == igtGesture) { idGestureName = IDS_SSGESTURE_FIRST + i; break; } } if (i == iCount && ID_MODE_GESTURES == m_nCmdMode) { iCount = countof(gc_igtMultiStrokeGestures); for (i = 0; i < iCount; i++) { if (gc_igtMultiStrokeGestures[i] == igtGesture) { idGestureName = IDS_MSGESTURE_FIRST + i; break; } } } return (IDS_GESTURE_UNKNOWN != idGestureName); } //笔势设置 void CAdvRecoApp::PresetGestures() { if (0 == ::IsWindow(m_hwndSSGestLV) || 0 == ::IsWindow(m_hwndMSGestLV)) return; ULONG iNumGestures = countof(gc_igtSingleStrokeGestures); ULONG iNumSubset = countof(gc_nRecommendedForMixedMode); for (ULONG i = 0; i < iNumSubset; i++) { if (gc_nRecommendedForMixedMode[i] < iNumGestures) ListView_SetCheckState(m_hwndSSGestLV, gc_nRecommendedForMixedMode[i], TRUE); } iNumGestures = countof(gc_igtMultiStrokeGestures); for (ULONG i = 0; i < iNumGestures; i++) { ListView_SetCheckState(m_hwndMSGestLV, i, TRUE); } }

如果需要源码,请留言留下email!

本文作者专著《Visual C++2010开发权威指南》即将推出,敬请关注,Visual C++2010最近技术,Windows7开发最新技术!

基于Visual C++2010与windows SDK fo windows7开发windows7平台的tabletpc应用(2)-轨迹多文档手写轨迹输入多语言识别范例相关推荐

  1. 基于Visual C++2010与windows SDK fo windows7开发windows7平台的tabletpc应用(1)-手写数学公式输入...

    搭建好Visual C++2010与windows SDK fo windows7的开发平台以后, 小试牛刀,检验下开发windows7的下的tabletpc应用,这个东西财务记账比较多, 大家先看效 ...

  2. 基于Visual C++2010与windows SDK fo windows7开发Windows 7的多点触摸特性应用程序(1)

    2008年5月28日,微软即将退休的精神领袖比尔·盖茨和首席执行官史蒂夫·鲍尔默共同在北圣地亚哥四季艾维亚拉洲际度假村举办的2008 D6 All Things数字化大会上向到场的嘉宾展示了windo ...

  3. 基于声网的音视频SDK和FreeSWITCH开发WebRTC2SIP Gateway 方案和思路

    为什么做这个? 今年初接到一个项目任务,客户要求在自己的音视频平台系统中集成webrtc功能(原系统是基于SIP协议开发的,已经稳定运行多年,有很多客户).在比对了多家RTC产品的效果后,.他们对声网 ...

  4. 计算道路超高lisp_基于Visual LISP的地铁轨道综合图辅助设计程序开发

    基于Visual LISP的地铁轨道综合图辅助设计程序开发 基于Visual LISP的地铁轨道综合图辅助设计程序开发 吴凯伟,石玮荃 (中铁工程设计咨询集团有限公司,北京 100055) 摘 要:为 ...

  5. Kinect for Windows SDK v2.0 开发笔记 (十) 高清面部帧(1) FACS 介绍

    转载于:https://blog.csdn.net/dustpg/article/details/38892783 使用SDK: Kinect for Windows SDK v2.0 public ...

  6. 基于JAVA小学生素质成长记录平台计算机毕业设计源码+数据库+lw文档+系统+部署

    基于JAVA小学生素质成长记录平台计算机毕业设计源码+数据库+lw文档+系统+部署 基于JAVA小学生素质成长记录平台计算机毕业设计源码+数据库+lw文档+系统+部署 本源码技术栈: 项目架构:B/S ...

  7. 基于JAVA基于Web的上门家教系统的设计与实现计算机毕业设计源码+系统+mysql数据库+lw文档+部署

    基于JAVA基于Web的上门家教系统的设计与实现计算机毕业设计源码+系统+mysql数据库+lw文档+部署 基于JAVA基于Web的上门家教系统的设计与实现计算机毕业设计源码+系统+mysql数据库+ ...

  8. 基于JAVA面相高校学生的图书共享平台计算机毕业设计源码+数据库+lw文档+系统+部署

    基于JAVA面相高校学生的图书共享平台计算机毕业设计源码+数据库+lw文档+系统+部署 基于JAVA面相高校学生的图书共享平台计算机毕业设计源码+数据库+lw文档+系统+部署 本源码技术栈: 项目架构 ...

  9. 基于JAVA计算机类专业考研交流学习平台计算机毕业设计源码+数据库+lw文档+系统+部署

    基于JAVA计算机类专业考研交流学习平台计算机毕业设计源码+数据库+lw文档+系统+部署 基于JAVA计算机类专业考研交流学习平台计算机毕业设计源码+数据库+lw文档+系统+部署 本源码技术栈: 项目 ...

  10. 基于java二次元信息分享平台计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署

    基于java二次元信息分享平台计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署 基于java二次元信息分享平台计算机毕业设计源码+系统+lw文档+mysql数据库+调试部署 项目架构:B ...

最新文章

  1. 003小插曲之变量和字符串
  2. 海康威视人证对比设备SDK-C#
  3. 超酷的JS时间效果--收集
  4. Twitter Storm常见模式
  5. python argparse理解与实例
  6. mysql done_MySQL 获取游标结果报错:1193-Unknown system variable ‘done’
  7. 补:小玩文件1-统计文本文件里的字符个数
  8. shiro学习(2):第一个shiro程序
  9. HttpServletResponse.getWriter().print乱码,request.getHeader乱码,解决方法
  10. mysql tableveiw与表格,javafx将数据库内容输出到tableview表格
  11. 对于DSH算法损失函数的理解
  12. html的定位属性,CSS之定位属性
  13. EasyObjects.Net
  14. 2021-09-13排序学习的特征
  15. COLING 2022提交要求与ACL模板要求记录
  16. rbw设计_同步调谐可变带通滤波器的设计
  17. spacedesk安卓_【图吧小白教程】安卓平板改数位板
  18. 今天再发一下热门关键字,看看能否推广网站
  19. 【LearnOpenGL】-PBR材质
  20. VLC保存网络流视频

热门文章

  1. 6场圆桌,20+演讲,48小时聚会, 2020全球区块链算力大会圆桌议题首度曝光
  2. python自己制作视频_你还在为看电影发愁?Python制作全网视频播放工具!
  3. 详解SR锁存器不定态
  4. 汉王手写板linux驱动下载,汉王笔手写板驱动程序
  5. Java抓取微博t.cn短链接的接口
  6. MathType编辑手写体
  7. 【编程开发】之国家代号与电话区号
  8. Spring学习(五):动态代理的两种实现方式(全网最容易懂)
  9. 【爆肝帝,花费3个月整理】金九银十面试季,2020-2021字节跳动所有,软件测试面试题拿走不谢!(附详细答案解析)
  10. 正离子计算机扫描检测,扫描电子显微镜