原文:通通WPF随笔(4)——通通手写输入法(基于Tablet pc实现)


从我在博客园写第一篇博客到现在已经有1年半了,我的第一篇博客写的就是手写识别,当时,客户需求在应用中加入手写输入功能,由于第三方的手写输入法都无法定制界面,所以领导决定自主开发,所以我就很简单地基于Tablet pc写了一个WPF控件,由于几个瓶颈问题,导致这个输入功能只能在我们的UI框架里使用,而无法做到像输入法那样可以输入到任意窗口。

  时隔1年半,随着各种项目的磨练,知识的积累几个问题得以解决,于是就产生了这个手写输入法。

ICO:

UI:

  

符号识别:

  

识别率还是比较高的

  

界面风格是1年半前设计的,当时觉得《创世纪》的视觉效果挺牛X的。

因为是针对于触摸设备设计的,所以没有做退出按钮,由应用来控制关闭。PC上的话,在空白处左键可以拖动,点击右键关闭窗口。

一、瓶颈问题


  由于本人C#出身,实在不想去研究什么IME等等底层的输入法机制,所以就写个exe实现输入法的功能。就面临下面几个问题:

  1、如何向其他窗口发送输入消息呢?

  2、如何知道当前键盘焦点所在窗口呢?

  3、如何在操作输入法窗体的时候不让目标窗口丢失焦点呢?

  这几个问题读起来就比较纠结......有句话说得好啊,“当做一件事时越来越难,就说明方向错了”。所以就绕开这几个问题呗。

二、解决问题


  C#里有个模拟键盘按键的方法 

模拟按键: 

System.Windows.Forms.SendKeys.SendWait("{DEL}");

而且可以发送字符:

System.Windows.Forms.SendKeys.SendWait("你好,美女~!");

  通过这个方法就模拟了键盘上的del键和发送字符串输入消息,而这个方法并没有需要窗口句柄,所以我猜想应该是模拟了底层的按键消息等等,而消息的去向肯定就是键盘焦点所在的窗口咯,这样就绕开了1、2两个问题。关于SendWait()参数的详细说明可以参看:http://msdn.microsoft.com/zh-cn/library/system.windows.forms.sendkeys.aspx

  接下来就需要解决的就只有3号问题了。

  一开始我很单纯的以为只要把窗口里面的所有控件都设置为不能获取焦点就行了

.Focusable = false;

  但这只是第一步,当一个窗口被激活时所有焦点都会跑到新激活的窗体上,所以,还得寻找其他方法。无意中在逛codeproject的时候发现了一段代码:  

[DllImport("user32.dll")]
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong); [DllImport("user32.dll", SetLastError = true)]
public static extern UInt32 GetWindowLong(IntPtr hWnd, int nIndex); // style of window?
int GWL_EXSTYLE = (-);
// get - retrieves information about a specified window
GetWindowLong(HWND, GWL_EXSTYLE);
// set - changes the attribute of a specified window - I think this stops it being focused on
SetWindowLong(HWND, GWL_EXSTYLE, (IntPtr)(0x8000000));

  Windows API的参数就是高端啊,完全看不懂是在干嘛,不过能达到目标就行。这样HWND窗口句柄对应的窗口就变得不会获取键盘焦点了。

  这样就解决了3个瓶颈问题。

三、手写识别


  已经实现了如何把字符串输出到其他窗口,剩下的就是识别手写墨迹了,核心在于InkAnalyzer这个类。通过WPF的InkCanvas控件来收集墨迹,然后通过theInkAnalyer.Analyze();方法就可以解析出来,十分方便。代码如下:(需要引用IACore.dll、IALoader.dll、IAWinFX.dll这3个动态库)

 InkAnalyzer theInkAnalyer;
AnalysisHintNode hint;
private void Grid_Loaded(object sender, RoutedEventArgs e)
{// style of window?
int GWL_EXSTYLE = (-);
// get - retrieves information about a specified window
GetWindowLong(HWND, GWL_EXSTYLE);
// set - changes the attribute of a specified window - I think this stops it being focused on
SetWindowLong(HWND, GWL_EXSTYLE, (IntPtr)(0x8000000)); theInkAnalyer = new InkAnalyzer();
hint = theInkAnalyer.CreateAnalysisHint();
hint.Guide.Columns = ;
hint.Guide.Rows = ;
hint.WordMode = true;
hint.TopInkBreaksOnly = true; } private void inkCanvs_MouseUp(object sender, MouseButtonEventArgs e)
{
hint.Location.MakeInfinite();
theInkAnalyer.RemoveStrokes(inkCanvs.Strokes);
theInkAnalyer.AddStrokes(inkCanvs.Strokes);
theInkAnalyer.SetStrokesLanguageId(inkCanvs.Strokes, 0x0804); theInkAnalyer.SetStrokesType(inkCanvs.Strokes, StrokeType.Writing);
AnalysisStatus status = theInkAnalyer.Analyze();
if (status.Successful)
{
for (int i = ; i < theInkAnalyer.GetAlternates().Count; i++)
{
Button thisButton = this.FindName("b" + i.ToString()) as Button;
string resultStr = theInkAnalyer.GetAlternates()[i].RecognizedString;
if (resultStr.Length==)
{
thisButton.Content = resultStr;
} } }
else
{
//MessageBox.Show("识别失败");
}
}

最终效果

  

  要在已安装了Tablet pc组件的Win7以上的系统才可以手写识别哦,win7完整版默认安装,但有的精简版把这个组件丢掉了,win8下完美运行。xp下的话得改一些系统文件,相关方法可以查看本人的第一篇博客 http://www.cnblogs.com/tong-tong/archive/2011/10/22/2220446.html

IACore等动态库下载:(包含XML注释文档)

http://files.cnblogs.com/tong-tong/IADLL.zip

demo下载:

http://files.cnblogs.com/tong-tong/TTHandwriting.zip

后记


  最近各种事情还要出钱啊、各种副省长还来参观啊、各种项目还没结束啊......

通通WPF随笔(4)——通通手写输入法(基于Tablet pc实现)的更多相关文章

  1. 通通WPF随笔(1)——基于lucene.NET让ComboBox拥有强大的下拉联想功能

    原文:通通WPF随笔(1)--基于lucene.NET让ComboBox拥有强大的下拉联想功能 我一直很疑惑百度.谷哥搜索框的下拉联想功能是怎么实现的?是不断地查询数据库吗?其实到现在我也不知道,他们 ...

  2. 通通WPF随笔(3)——艺术二维码素材生成器

    原文:通通WPF随笔(3)--艺术二维码素材生成器 最近公司让我开发一个条形码的生成控件,花了半天时间搞定觉得不过瘾,什么年代了该用二维码了吧.于是wiki了一下二维码的资料. 比较常见的就是QR码( ...

  3. 通通WPF随笔(2)——自己制作轻量级asp.net网站服务

    原文:通通WPF随笔(2)--自己制作轻量级asp.net网站服务 大学玩asp.net时就发现VS在Debug时会起一个web服务,这东西也太神奇了服务起得这么快,而相对于IIS又这么渺小. 前几个 ...

  4. c#基于Tablet pc实现的手写输入

    需要安装Tablet pc,win7的话 直接在控制面板>程序和应用>添加组建里面勾选上添加 然后就是下面的程序了,看代码 设计文件 namespace 手写识别 { partial cl ...

  5. WPF随笔(九)--使用路径动画模拟管道流体流向

    原文:WPF随笔(九)--使用路径动画模拟管道流体流向 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/lordwish/article/detail ...

  6. wpf随笔

    因项目需要查找wpf.DataGrid的Binding方法, 由于其属于Dev框架体系内,偏向于winform并无Binding 1.且线程外更改UI控件还需要委托或者action,而Wpf控件仅需要 ...

  7. 循环移位法和数据拼接法基于led

    功能描述 让led每隔0.5s从两边向中间闪烁,然后在从中间向两边闪烁,不断循环 项目实现 开发板 晶振为50M,那么达到0.5s时计数器count1需要达到24_999_999这么多次数 计数器代码 ...

  8. 商米D1S一体机设置搜狗手写输入法图解

    按照下图步骤,一步步设置即可,询问全新的时候需要点击允许. 商米应用市场搜索下载搜狗输入法,并安装 安装完成后,点击桌面搜狗输入法,选择启用搜狗输入法,如图 点击启用后,在虚拟键盘中选择搜狗输入法,并 ...

  9. iOS 手写输入法奔溃,替换隐藏键盘方法

    {   UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:se ...

随机推荐

  1. maven打包到本地库

    mvn install:install-file -DgroupId=com.alipay -DartifactId=com.alipay.core -Dversion=20180104135026 ...

  2. 【u245】机房病毒

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 我们机房中了病毒,因此几乎什么都无法正常进入.为了解决这个病毒,我们花了好几天.终于在大家的共同努力下 ...

  3. [React Router v4] Render Catch-All Routes with the Switch Component

    There are many cases where we will need a catch-all route in our web applications. This can include ...

  4. 新技能 get —— Python 断点续传下载文件

    from urllib.request import urlretrieve import sys import os prev_reported_download_percent = None # ...

  5. Opencv Sift和Surf特征实现图像无缝拼接生成全景图像

    Sift和Surf算法实现两幅图像拼接的过程是一样的,主要分为4大部分: 1. 特征点提取和描述 2. 特征点配对,找到两幅图像中匹配点的位置 3. 通过配对点,生成变换矩阵,并对图像1应用变换矩阵生 ...

  6. 【codeforces 779B】Weird Rounding

    [题目链接]:http://codeforces.com/contest/779/problem/B [题意] 问你要删掉几个数字才能让原来的数字能够被10^k整除; [题解] /* 数字的长度不大; ...

  7. 【codeforces 534C】Polycarpus' Dice

    [题目链接]:http://codeforces.com/contest/534/problem/C [题意] 给你n个奇怪的骰子,第i个骰子有di个面; 然后给你n个骰子的点数之和; 问你每一个骰子 ...

  8. FPGA综合优化

    1 速度和面积 在全面优化水平将达到速度和面积RTL要利用逻辑拓扑的优势. 供FPGA由于在后端而言缺乏知识,门级优化.普通情况下更高的速度要求更高的并行性以及更大的面积,可是在某些特殊情况下并非这样 ...

  9. 一段node代码的解读

    path.join(path.dirname(__dirname), platform); __dirname:全局变量,变量获取当前模块文件所在目录的完整绝对路径 path.dirname():返回 ...

  10. android:layout_gravity和android:gravity属性的差别

    gravity的中文意思就是"重心",就是表示view横向和纵向的停靠位置 android:gravity:是对view控件本身来说的,是用来设置view本身的文本应该显示在vie ...