刚买了夏新 N810,这是我使用的第一个智能手机,装了 WM6.5 折腾了一个多月,觉得挺好的,最后在装了 14M 雅黑字体后,频繁死机,又一次装了汉王马兰花后,直接不能启动了。后在模拟器上证实,汉王马兰花确实有这个问题。现在用三星手写和 10M 雅黑,目前没发现问题。
WM6.5 虽然不错,只是内存占用比 WM6.1 大 3M 左右,N810 又是内存不足的机型,于是又刷回 WM6.1,基本都不错,反映似乎还快一点儿,只是不能习惯 6.1 的开始菜单了。于是在网上找了不少程序,我的需求不多,只要点“开始”能直接出现“程序”界面,再有个方式进入设置,就行了,可惜,能找到的基本都是大型程序,很华丽,很强大,不过,占用系统资源太多。一番搜索测试之后,决定自己写一个插件。
基本的想法是,一个今日插件,4 个快捷栏位,其中两个是“短信”和“电话”,另外两个,一个是“程序”,一个是“设置”。
于是开始折腾,从 WM SDK 里找到今日插件 Memwatcher 的例子程序,程序是 C++ 的,不过也好,这样占用资源会少一点儿,从 ROM 里提取的信息中,找到未读短信数量读取注册表“System\\State\\Messages\\sms\\Unread”,而未接来电数量读取“System\\State\\Messages\\TotalEmail\\Unread”,只要在 WM_TODAYCUSTOM_QUERYREFRESHCACHE 消息中检测这两个值就可以了;在网上找到启动短信的命令行“\\Windows\\tmail.exe -service "SMS"”,不过,启动电话的程序,启动起来时,并不是呼叫记录界面,而是拨打界面,虽然不知道怎么直接进呼叫记录界面,整体进度还算满意。
然后遇到“程序”和“设置”,就是一头雾水了。这两个东西,不是独立程序,用 Remote Process Viewer 查看,发现都是属于 Shell32.exe 进程的,要由第三方启动它们,似乎有点儿难。上网查找,也没个结果。尝试在系统中查找“开始”菜单,然后查找“程序”和“设置”菜单,再用 SendMessage 的方式启动,不过,WM 上没有 GetTopWindow,也缺少很多其他的 Menu 相关函数,从例子程序 Dynamenu 中找到几个 SHxxxMenu 函数,复制到我的程序里,用 Remote Spy 发现开始菜单的窗口是“HHTask”,于是查找窗口 hwnd,查找 Menubar,再查找 Menu,遇到瓶颈,那几个 SHxxxMenu 函数,需要 Menu ID 作为参数,我就是要找 Menu ID,如果知道的话,何必再找?另外,用 Remote Spy 监视 HHTask 和 Desktop 的消息,在点击开始菜单项时,并没有出现 WM_COMMAND 消息,这可奇怪了,不用 WM_COMMAND 它是怎么处理菜单项点击的呢?或者说,它为什么要和普通程序不一样呢?不解。
反复碰墙后,决定放弃启动“程序”和“设置”,其实,“设置”本身并不常用,即使现在的开始菜单也行了,于是就有两个方案:一,4 个快捷栏位可设置,随便什么程序都可以;二,自己实现一个“程序”面板,还可以顺便实现按照使用次数排序,其他 3 个栏位给最常用的 3 个程序,最好再加入同步现有“程序”目录中的快捷方式。于是搜索了一下快捷方式的读取问题,再检查 WM 中的 快捷方式文件,发现和 Windows 的快捷方式格式不一样。最后决定,还是使用第一个方案,4 个快捷栏位可设置,另外再用 .Net CF 编写一个设置程序。
现在,需求有些变化,今日插件需要能读取 exe 文件的图标,网上查找之下,知道可以用 SHGetFileInfo 取得。
.Net CF 确实比使用 C++ 方便多了,不过,发现 WM 系统的 OpenFileDialog 对话框只能显示 My Documents 中的几个目录,对我的需求来说,一点儿意义都没有,而且没有设置,无法让它支持其他目录。网上搜索了一下,确实有不少抱怨,也找到了一个
定制控件和它的
增强版本,只是这个控件不算完善,比如最下边是输入框,但是整个窗体却不能在打开输入法的时候自动调整大小,控件也只能每次使用重新创建,否则会出现多个 Cancel 菜单以致出错,不支持单击选择等,不过,总体来说,够用了。在写设置程序的时候,终于解开了我的一个疑惑:为什么在 WM 上,点右上角的“X”,程序却并不关闭,原来,“X”在 WM 中是最小化的意思,“OK”才是关闭,多愚蠢的设计啊 —— 也造成网上流传“点X关程序的软件”……
最后一个问题是,通知今日插件配置已修改,重新读取,于是定制了窗口的 Class 和 Title,在设置程序里使用 FindWindow 查找,返回 0。查 MSDN,发现 FindWindow 函数只查找顶级窗口,而今日插件是 Desktop 的子窗口,所以找不到,只能先找 Desktop,再使用 FindWindow 查找子窗口,然后使用 SendMessage 发送 WM_APP 通知,在经历了几个低级错误的折磨之后,整个插件的制作总算完工。本来预计 1、2 天完成的,实际上还是扎实的用了 3、4 才做完。当然,需求的细节已经和最初不太一样了。
在 WM5 和 WM6.5 的模拟器上测试都成功,又安装到 N810 上,也运行良好,.Net 程序在模拟器上启动的时候,会先出个等待图标,但是,在手机上没感觉到,看来,现在的手机速度确实够快了。
虽然没有实际测量,不过估计单就今日插件来说,使用的内存大致在 30K 左右吧,而它很少需要重绘,所以对 CPU 的使用也可以忽略。
这个插件安装过后,并不会立即显示出来,必须先到今日设置里看一眼它,或者重新启动手机,才会显示出来,另外,目前只支持 QVGA 屏幕,这几个问题还没有解决,不过不算大问题,留待以后吧。
下面是插件我的手机上的运行截图和插件的下载:(顺便鄙视一下 JavaEye,移动开发那么多选项,竟然没有 Windows Mobile ?)
PS:一觉醒来,想到在重新读取设置的时候,忘了使用 DestoryIcon 释放以前的图标,虽然“重新读取设置”不是一个经常调用的功能,还是修正了,重新上传。