基于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开发最新技术!
再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow
原文地址:https://www.cnblogs.com/wicnwicnwh/p/10308869.html