WM有约II(二):持续改进
WM有约II(二):持续改进
Written by Allen Lee
自定义"你在干嘛?"
在上一集结束的时候,我们发现一个极其严重的问题——这个应用程序会忽略我们最初希望截获的"你在干嘛?"!这怎么行?好,马上添加一个Configuration.xml:
代码 1
这段配置信息包含了4个截获设置,它们分别用于截获"计算机"版、普通话版、广东话版和英文版的"你在干嘛?"。每个截获设置都会有一个comparisonType属性,它是用来指定比较方式的,Equal意味着只有短信息的内容和指定的字眼相等才把它截下来,而Contains则意味着只要短信息包含指定的字眼就把它截下来。
上面这段配置信息是用来构建MessageInterceptor对象的,这项工作将会由InterceptionManager来负责,而完成这项工作的代码将会放在它的构造函数里:
代码 2
这段代码首先使用Helper.MapPath方法获取配置文件的完整路径,接着把配置信息读到XElement对象里,然后根据这些信息构建出MessageInterceptor对象,最后把构建好的对象存到"本地"。需要说明的是,comparisonType属性所使用的值其实就是MessagePropertyComparisonType枚举的字面值,所以这里直接使用Enum.Parse方法来解析这些值。如果你读过第一辑的《WM有约》,那么你应该不会对Helper.MapPath方法的实现感到陌生:
代码 3
好了吗?还没有,因为我们还没告诉这些MessageInterceptor如何处理截获的短信息。InterceptionManager提供了AttachInterceptionHandler方法,可以协助我们完成这项工作:
代码 4
有了这些准备,我们就可以把使用MessageInterceptor的代码(参见《WM有约II(一):你在干嘛?》代码4)改成使用InterceptionManager了:
代码 5
自定义状态
在上一集里,我们把可选的状态直接写在代码里(参见《WM有约II(一):你在干嘛?》代码3),这种做法当然是不推荐的;在这一集里,我们将会把这些状态挪到配置文件里。首先,在Configuration.xml里加入下面这段配置信息:
代码 6
这些信息的读取是由StatusTextManager来负责的,而完成这项工作的代码将会放在它的构造函数里:
代码 7
这里之所以选用BindingList<T>来存储数据主要是为了实现数据绑定,当集合里的数据发生改变时,用户界面上的那个ComboBox里的数据会跟着调整,而StatusTextManager也会把改变后的数据保存到配置文件里:
代码 8
有了这些准备,我们就可以使用StatusTextManager来读取配置文件里存储的状态数据了:
那么,用户如何编辑这些状态信息呢?总不见的让用户直接修改配置文件吧?于是,Status Texts Editor诞生了:
图 1
这个窗体在构造的时候会从StatusTextManager那里取得状态数据,然后绑定到ListBox上:
代码 9
一开始,这个窗体下面的4个控件(一个Label、一个TextBox和两个Button)都是隐藏的(Visible属性值为false),当用户单击Add按钮或者Modify按钮时,这4个控件就会显示出来,并把m_OKAction设为OK按钮此时应该执行的操作:
代码 10
代码 11
OK按钮将负责执行m_OKAction委托所指定的操作:
代码 12
而Cancel按钮则负责把这4个控件隐藏起来:
代码 13
Remove按钮的代码也非常简单:
代码 14
至于ShowControls方法和HideControls方法,只不过是把那4个控件的Visible属性设为相应的值,比较简单,就不在这里展示它们的代码了。
现在万事俱备,只欠主窗体上的一个按钮了:
图 2
最后就是在用户单击这个按钮时打开Status Texts Editor:
代码 15
选择联系人
目前,这个应用程序还有一个地方做得不够好的,也是上一集结束时提到的,当用户想查询某个朋友的状态时,要手动输入对方的手机号码,于是萌生了让用户可以通过另一个对话框选择联系人里面的手机号码,不过这次我不打算自己开发这样一个对话框了,因为Windows Mobile 6 Professional SDK已经提供了一个很好的ChooseContactDialog了!
首先,在主窗体上添加一个按钮:
图 3
接着,引用Microsoft.WindowsMobile.Forms.dll以及Microsoft.WindowsMobile.Forms和Microsoft.WindowsMobile.PocketOutlook两个命名空间。好了,现在我们可以使用ChooseContactDialog了:
代码 16
上面这段代码会对联系人进行过滤(通过RequiredProperties属性),只显示有手机号码的联系人,当用户单击ChooseContactDialog对话框上的OK按钮时,选中的联系人的手机号码将会显示在TextBox上。
表演时间到了!
应用程序启动的时候,状态列表里的第一个状态(在这里是"I'm free now.")将被设为当前状态:
图 4
单击ComboBox右边的按钮打开Status Texts Editor:
图 5
单击Add按钮添加一个新的状态:
图 6
单击下面的OK按钮保存这个状态,然后关闭Status Texts Editor。
现在,我们来测试一下这个应用程序能否截获"你在干嘛?",打开Cellular Emulator,并用它向模拟器发送"What are you doing now?"(因为我没有安装中文版的模拟器镜像~):
图 7
嗯,没问题,接着向模拟器发送"{Trombone:PingStatus}",居然没有截获!
图 8
怎么回事?目前这些MessageInterceptor对象是存放在InterceptionManager内部的集合里,如果我把它们"提取"出来,以一个个私有成员的形式放在主窗体里会怎样呢?
图 9
正如上图所示,"What are you doing now?"和"{Trombone:PingStatus}"两条短信息都顺利截获并成功返回当前状态!真是非常郁闷啊!一时三刻我也想不出什么解决方法,只好硬着头皮把截获设置写到代码里了~~~如果你有好的想法,欢迎提出!
接下来,我们看看ChooseContactDialog对话框,单击主窗体下面那个TextBox右边的按钮,将会打开ChooseContactDialog对话框:
图 10
选中一个联系人,然后单击Select菜单项,ChooseContactDialog对话框将会关闭,选中的联系人的手机号码将会显示在主窗体下面那个TextBox里:
图 11
单击Ping按钮,Cellular Emulator将会收到模拟器发送的短信息:
图 12
你还想要什么?
很久很久之前我就明白一个道理,想要的东西不可能全部都得到,但我就是不甘心,我应该就此作罢吗?我知道我很任性,常常执着于这些看起来很不应该的事情,但我只是不想留下遗憾。我决定在结束这篇文章之前再测一次InterceptionManager。
这次,我关闭并重新打开Cellular Emulator,软重置模拟器,然后通过Visual Studio 2008再次运行应用程序。啊~~~~~~
图 13
我到底应该说"奇迹"还是"奇怪"?我用Cellular Emulator依次向模拟器发送以下短信息:
- What are you doing now?
- {Trombone:PingStatus}
- Hey, boy. What are you doing there?
- {Trombone:PingStatus}
所有短信息都顺利截获并成功返回当前状态!我已经彻底无语了~~~
下一集,我们将会尝试扩展查询状态的功能,使之可以查询Outlook Mobile里面的信息。