基于Visual C++2010与windows SDK fo windows7开发windows7平台的tabletp

基于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

时间: 2024-07-28 23:23:28

基于Visual C++2010与windows SDK fo windows7开发windows7平台的tabletp的相关文章

基于Visual C++2010与windows SDK fo windows7开发Windows 7的多点触摸特性应用

2008年5月28日,微软即将退休的精神领袖比尔·盖茨和首席执行官史蒂夫·鲍尔默共同在北圣地亚哥四季艾维亚拉洲际度假村举办的2008 D6 All Things数字化大会上向到场的嘉宾展示了windows7的测试版.     鲍尔默向记者打趣道:"今天只给你们看一丁点儿(just a snippet)哟!"然而就是那么一丁点儿,已经让世界为之惊艳! 盖茨和鲍尔默在D6 All Things数字化大会上重点展示的是多触点技术(multitouch technology),这是运行Wind

[入门级] 基于 visual studio 2010 mvc4 的图书管理系统开发初步 (二)

[入门级] 基于 visual studio 2010 mvc4 的图书管理系统开发初步 (二) Date  周六 10 一月 2015 By 钟谢伟 Category website development Tags asp.net / mvc4 相关资源 ibatis manual pro git 廖雪峰的官方网站 BookMS-V1.0 上一篇链接 任务简介 开发工具:VS2010 项目框架:MVC4 浏览器:Chrome 数据库ORM框架:iBatis.net 数据库:mysql 后端开

基于Visual C++2010与office2010开发办公自动应用(1)在自己的程序里面打开office文档

分享一下我老师大神的人工智能教程吧.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net Office 2010,是微软推出新一代办公软件,开发代号为Office 14,实际是第12个发行版.该软件共有6个版本,分别是初级版.家庭及学生版.家庭及商业版.标准版.专业版和专业高级版,此外还推出Office 2010免费版本,其中仅包括Word和Excel应用.除了完整版以外,微软还将发布针对Office 2007的升级版O

Kinect for Windows SDK v2.0 开发笔记 (十五) 手势帧

 (转载请注明出处) 使用SDK: Kinect for Windows SDK v2.0 public preview1409 同前面,因为SDK未完成,不附上函数/方法/接口的超链接. 这次终于是新的东西了,是"手势帧",不过原名是"可视化手势构建器"(Visual Gesture Builder)帧,是 SDK 2.0自带的手势解决方案,不过,如果您觉得微软写得不可靠,甚至垃圾,您可以尝试自己写个,笔者在 提供的范例中,写了个简单的样子(几十行而已,不要期

DirectX11--使用Windows SDK来进行开发

在看龙书(Introduction to 3D Game Programming with Directx 11)的时候,里面所使用的开发工具包为Microsoft DirectX SDK(June 2010),该开发包到现在也已经经历了8年左右.而现在,微软其实已经将DX的相关组件随同Windows SDK一同更新,并不再对DirectX SDK做任何的更新.若你使用的是Visual Studio 2017,可能会发现系统库内已经默认包含了D3D11.h等DX11开发相关的头文件.对于之前龙书

Kinect for Windows SDK v2.0 开发笔记 (十六) SDK2.0正式发布 与 自带工具

(转载请注明出处) 使用SDK: Kinect for Windows SDK v2.0 1409 来了,微软于10月22日正式发布了SDK v2.0,前兆是发现了API文档正常了... 话说为什么是1409而不是1410 于是从这节开始,开始附上API的超链接.正式版的体积也是可观,整整(比7月版)大了一倍 这节说说自带的软件,本打算录下来,但是太懒了 先附上微软自己的地址,Part1,Part2,这是手势的,虽然是使用C#,不过工具使用是完全一样的. 先看看SDK中自带的工具: 0. Kin

Kinect for Windows SDK v2.0 开发笔记 (十七) 深度帧3D

 (转载请注明出处) 使用SDK: Kinect for Windows SDK v2.0 1409 这节算是补充节吧,以3D方式显示深度帧,SDK更新的则在后面的章节说明. 之前想错了,以为每帧显示所谓的点云,GPU负担很大, 背景每帧都要传送 500 * 400 * 3 * 4 , 才2M的数据,之前估计错了. 3D接口依然是D3D11,这次简单多了,顺带复习一下吧 要点: 0. 初始化..  仅仅需要: IKinectSensor(使用 GetDefaultKinectSensor)

Kinect for Windows SDK v2.0 开发笔记 (十一) 高清面部帧(2) 面部特征对齐

(转载请注明出处) 使用SDK: Kinect for Windows SDK v2.0 public preview1408 根据前一节的说明,这节就是关于面部特征对齐的. 接口为IFaceAlignment,因为SDK还在Beta中,提供官网的连接可能会失效,所以不提供了. 需要可以到微软官方查询.目前,面部特征对齐主要可以干: 0. 获取面部外框 -- 面部帧也能.但是经测试,精度高得多,抖动大概在几像素内 1. 获取头部旋转中心 --结果是一个相机空间坐标,大致位置就是颈部中心 2. 获

Kinect for Windows SDK v2.0 开发笔记 (十三) 高清面部帧(4) 面部模型构建器

 (转载请注明出处) 使用SDK: Kinect for Windows SDK v2.0 public preview1409 同前面,因为SDK未完成,不附上函数/方法/接口的超链接. 这次让我们让面部捕捉更加稳定/精确吧! 自从一直8月有了高清面部帧的例子后,觉得IFaceModel::GetFaceShapeDeformations它不干正事,一直返回0.0f的数据. 与其他开发者简单交流后,发现了问题的根本所在,需要面部模型构建器(IFaceModelBuilder). 好了,那么