一键按下 响起模拟来电
技术与开发
当你需要一个借口,希望手机响起来电铃声,借此离开,只要用手轻轻一碰手机,奇迹就会出现……
模拟来电设计思路
与网友约会,不小心碰到恐龙;MM约你压马路,老爸却要你陪他看球……很多时候,你是否十分期待你手机的来电铃声欢快地响起:“你有一个电话……”,拯救你于水火之中?这就是我们要模仿开发的模拟来电功能。
有了这个工具(下载地址:http://www.shudoo.com/bzsoft),只需要你的手划过手机时,轻轻地碰一个按键,一个设定好的来电就激活了。要开发这个工具,先要设计一个来电界面,然后从电话簿中读取联系人的详细信息,并将联系人信息显示到窗体上,再响起来电铃声和开启震动(图1)。

如何调用联系人
要调用联系人,就要用到POOM。POOM(Pocket Outlook Object Model )是基于微软技术的一套针对手机上个人信息管理的接口库。 POOM不仅包含了对联系人信息的操作,还包含了任务、约会提醒等关于个人信息管理的内容。
在Windows Mobile 5之前,要想访问联系人等信息,我们只能借助POOM中的本地API。伴随着Windows Mobile 5的发布,在Windows Mobile 5的SDK中,公布了下面几个托管函数命名空间:Microsoft.WindowsMobile.Configuration、 Microsoft.WindowsMobile.Forms、Microsoft.WindosMobile.PocketOutlook、Microsoft.WindowsMobile.PocketOutlook.MessageInterception、Microsoft.WindowsMobile.Status、Microsoft.WindowsMobile.Telephony。
利用它们,可以很方便地完成以前必须借助本地函数才能实现的功能。为了访问联系人信息,我们需要使用“Microsoft.WindowsMobile.PocketOutlook”命名空间的一些对象,读取该联系人的各种信息,例如姓名、电话、地址、类别等。
利用POOM,可以随意控制PPC和SP上的E-mail、短信、联系人、约会、任务,可以开发电话簿管理程序,可以开发短信管理程序,可以开发电话簿、短信息备份程序及个人事务管理程序等。
模拟来电设计步骤
第一步:创建项目
启动Visual Studio 2008,选择“文件→新建项目”。在弹出的“新建项目”的“项目类型”中选择“Visual C#→智能设备”,“模板”选“智能设备项目”,“名称”设为“IncomingCall”。在弹出的“添加新智能设备项目”对话框中,“目标平台”选择“Windows Mobile 5 Professional SDK”,“.Net Compact Framework 版本”选择“.Net Compact Framework Version 3.5”,“模板”选“设备应用程序”完成项目创建。
第二步:设计界面
右击“解决方案资源管理器”中的“Form1.cs”,重命名为“FormIncomingCall.cs”,Visual Studio 2008的重构功能会自动将该窗体的类名修改为“FormIncomingCall”。在“窗体设计器”选中该窗体,在“属性”浮动窗口中修改该窗体的“Text”属性为空。选中“MainMenu1”,添加两个子菜单,分别命名为“menuItemAnswer”、“menuItemIgnore”,子菜单的“Text”属性分别设置为“接听”、“拒绝”。
“智能设备项目”中的窗体,总是充满屏幕的,而我们需要的来电界面,是一个非全屏的窗体。右击“窗体设计器”中的“FormIncomingCall窗体”,点击“查看代码”修改FormIncomingCall中的代码(修改后的代码下载地址为:http://www.shudoo.com/bzsoft)。
第三步:读取联系人信息
按一个键(可以自己设置),访问手机电话簿,读取预定的联系人信息。要实现这个目的,需引用“Microsoft.WindowsMobile.PocketOutlook”命名空间,该命名空间中提供了访问手机电话簿的函数。
依据实际来电界面,将获取的联系人信息绘制到非全屏窗体“FormIncomingCall”上。在这里,我们需要重写类“FormIncomingCall”的“OnPaint”,它在窗体需要重新绘制时被调用。关键代码如下所示(完整代码下载地址为:http://www.shudoo.com/bzsoft):
g.DrawRectangle(new Pen(ForeColor, 4), new Rectangle(0, 0, 229, 160));//绘制外框
g.FillRectangle(new SolidBrush(SystemColors.ActiveCaption),
new Rectangle(2, 2, 226, 20));//绘制标题栏
g.DrawString("电话 - 拨入", Font,
new SolidBrush(SystemColors.ActiveCaptionText), 10, 5);//绘制标题文本
g.DrawString("中国移动\r\n\r\n来电\r\n\r\n"+
contact.FileAs +// 姓名
"\r\n" +
contact.MobileTelephoneNumber + //移动电话
第四步:播放来电铃声
我们需要来电界面显示的同时,播放来电铃声。在窗体设计器中双击“FormIncomingCall”窗体,添加窗体Load事件的响应,并将播放的代码加入“FormIncomingCall_Load”中。这一步的关键就是从注册表中[HKEY_CURRENT_USER\ControlPanel\Sounds\RingTone0]读取铃声文件路径。关键代码如下所示(完整代码下载地址为:http://www.shudoo.com/bzsoft):
string GetRing()
RegistryKey registryKey =
Registry.CurrentUser.OpenSubKey(@"\ControlPanel\Sounds\RingTone0");
string ringFileName = registryKey.GetValue("Sound").ToString();
return ringFileName;
soundPlayer.SoundLocation = GetRing();// 仅支持播放WAV文件,如:"\\Windows\\You have an incoming call.wav";
soundPlayer.PlayLooping();// 播放来电铃声
第五步:打开震动
.Net CF 尚未直接提供控制震动的方法。这里我们需要通过“P/Invoke”方式调用系统API。在“coredll.dll”中有这样两个函数:
BOOL WINAPI NLedGetDeviceInfo( UINT nInfoId, void *pOutput );
BOOL WINAPI NLedSetDevice( UINT nDeviceId, void *pInput );
NLedGetDeviceInfo是用来获得LED数量,NLedSetDevice是用来设置LED状态,我们可以通过它们来启动或者关闭Pocket PC设备的震动。
注意,一般PPC设备都有两个LED,一个是扬声器0(Radio LED),另一个则是振动器1(Vibrator)。不同机器的振动器,其设备index可能不同。 我们创建一个类“LED”,用以实现对振动器的控制。相关代码请到http://www.shudoo.com/bzsoft下载。
当点击“接听”或“拒绝”菜单的时候,需要执行相应的关闭动作。在窗体设计器中分别双击“接听”和“拒绝”菜单,添加菜单Click事件的响应,并将结束动作的代码加入事件响应中。关键代码如下所示(完整代码下载地址为:http://www.shudoo.com/bzsoft):
private void menuItemAnswer_Click(object sender, EventArgs e)
{ /点击了"接听"
menuItemIgnore_Click(sender, e);
private void menuItemIgnore_Click(object sender, EventArgs e)
{
soundPlayer.Stop();// 关闭铃声
led.SetLedStatus(LED.Status.OFF);// 关闭震动
第六步:运行程序
在Visual Studio 2008中点击菜单“调试→启动调试”(或者直接按F5),在弹出的部署对话框中选择“Windows Mobile 5 Professional Emulator”,点击“部署”,就可以在模拟器中看到运行效果了(图2)。

读者反馈
开发QQ群:看了上期的文章,我想问问截图保存格式如何设置为JPG?
小编:在上期文章中,截图保存的只是界面上每个像素点的颜色信息,用的是数据格式。如果要将截图保存成特定格式的图片,例如JPG,则要编写逻辑代码将颜色信息转换为特定格式的图片。
开发QQ群:请教一下,有没有检测手机程序的工具?
小编:有的,手机程序的检测,主要有两种方式:内存检测和效率检测。内存优化,可以使用WTK中提供的内存检测工具,检测内存使用的情况,如果发现内存占用太高,就要对程序进行修改。
效率优化,使用的是WTK中提供的方法检测工具,检测效率执行是不是存在瓶颈,找到问题后就可以对程序进行修改。内存检测和方法检测都是在WTK程序菜单的“Preferences→Monitor”中设置。
开发QQ群:我研究了《电脑报》提供的手机五子棋游戏代码,产生了一个想法,想在五子棋游戏中添加一个倒计时功能,这样当联网下棋时就有时间限定了。小编觉得我的这个提议如何?
小编:这个建议很好,也是常见的一种游戏规则。在实际编程时,只需要在程序运行时开启一个专门的计时线程进行计时就可以了,在时间结束时规定本局失败。如果你已经把五子棋程序改成网络版了,则需要修改服务器端的规则,在服务器端编写计时逻辑,然后将计时信息传递给客户端。
开发QQ群: 在下载手机软件时,分为Nokia S40、S60等版本,怎么还有通用版本,这些版本之间有哪些区别呢?
小编:手机软件和计算机上的软件不一样,由于不同手机之间硬件的差异,例如屏幕大小以及支持的软件不一样,所以同一个手机软件需要出多个版本,从而适应不同的软硬件环境以充分发挥手机的性能,所以就出现了专用版本。而手机的型号太多,对每个系列都编写专门的版本不太现实,所以就出现了通用版本。一般情况下,由于要做到通用,通用版本的功能与专用版本的功能相比稍微弱一些。
读者问题:我要在手机程序中设计一个定时器,定时器会调用函数访问一个类的成员,我应该怎么设计?
高手 云哥:如果为了访问方便,且该成员的数值在该类各个对象中都需要保持一致,则可以使用static修饰符来修饰该成员,这样方便程序的访问。如果有多个线程都要访问该成员,则在处理该成员时一定要注意数据的同步。
读者问题:在发送手机短信时,如何获知短信是否发送成功?
你是手机编程的高手吗?你能解答上面这位读者的疑问吗?不要犹豫,来我们这里展示一下你的风采吧,来信请发到pcw-chendx@vip.sina.com(也可以给我们发送问题)。
第四个QQ群: 9822280,验证码:手机开发,欢迎对手机编程感兴趣的朋友加入。