用WM和IPhone都有很长时间了,IPhone是不错,但是对于我这样的UI饭来说,几年了,一成不变的UI是可耻的,对于我来说无论是IPhone 2G还是3G还是3GS,都没有很大的区别,哦,除了几个应用程序和照相的像素以外(很可惜我照相不用手机)。不过IPhone是很不错,在我心目中比WM的分数要高,因为操作很方便,简单,唯一的缺点就是UI太没变化了。相比之下还是WM有变化。
最近刷了一个新的系统,虽然内存占用多一点,不过操作方便了很多,可定制性也很多,基本上完全取代了WM本身的短信,设置等等功能,完全大变样。发短信接短信也可以即时刷新Touch Flo了,不用再重新刷新。这点确实不得不赞一下WM的可定制性,但是这个好处只对于类似我这样的高级玩家,对于普通用户来说,我觉得还是IPhone比较适合,操作好,UI也行,至少耐看。


另一个好处就是快捷方式,现在的WM可以将联系人,收藏夹作为快捷方式了,就像上面屏幕里面的一样,我要给我女友打电话,直接按一下就可以了,或者想访问我的一个最爱的收藏,直接也可以设置一个快捷方式,这个地方着实节约了我不少时间。喜欢的可以去这个帖子下载。
今天继续完善一下程序,然后做安装程序,就想要定义一下Windows Mobile 6.5开始菜单的图标,不过这里图标定义的还是有点复杂,主要是作图有点复杂吧,而且网上说的办法也一点都不好。现在先上两张图,就是我的WM机器的UI以及我自定义的UI。

我们可以看到第一个图是一个shell,WM在UI上还是做了很大的改动的,另外这里只是为了让配图好看加上去的,如果想要这个shell可以留下邮件,安装了之后可以看到还是蛮不错的。第二个图就是我们的程序图,程序图这里的Poewer Management是我开发的程序,这里就介绍如何让自己的程序放到开始菜单里,而且WM 6.5的系统中,还可以通过设置PNG作为我们程序的图标,更透明UI更友好。

首先我们为我们的程序添加一个png图片(注意这里编译的时候要设置为Copy Always),这个图片是要显示在WM开始菜单的,并且这个图片的分辨率最好是192,然后我们添加一个安装包,在安装包内添加我们需要的内容,如上图,添加完成后,我们就需要在安装包的文件系统里面添加一个【特殊文件夹】,如下图所示。

上面我已经添加了一个Start Menu Folder,所以在菜单里面是灰色的,选不了了,上图只是示意在哪里选择,然后我们在右侧的窗口中创建快捷方式,如下图。

创建快捷方式我们就能够在开始菜单中看到我们的ICON了,但是先别急,我们可以试试安装,发现图标很丑,所以这里才到真正的正文,如何自定义WM6.5的开始菜单,这里我们可以通过修改注册表的方式修改,如下图所示。

其中注册表的规则如下。
[HKEY_LOCAL_MACHINE\Security\Shell\StartInfo\Start\Phone.lnk]
“Icon“=“\Application Data\My App\newphoneicon.png“
我们写的时候,在Start里面创建的键就是我们程序的快捷方式,也就是我们刚刚创建的一个开始菜单的同名的lnk文件。(也就是我刚才创建了一个Power Management快捷方式,在注册表里面也是同名),然后在这个键里面添加一个String键,值就是我们的ICON的地址,这里我使用了%InstallDir%来表明安装路径。
这样,程序启动之后WM开始菜单的图标就不会那么模糊那么丑了,我们就可以自定义自己的快捷方式的图标了。下面这个链接是参考资料,例如何种屏幕的开发何种类型的WM的手机应用应该用何种大小和分辨率的图片都会详细介绍。
最近一直在看Windows Mobile UI方面的东西,自己不是很熟悉,所以就请教了一些其他的朋友,比如Jake,如果在WM上面有什么不懂的,大可以请教他,是个高手,很强,现在在国外工作。
由于自己用的是Windows Mobile HTC Touch Diamond 2,所以觉得UI很重要,很早之前用其他的东西的时候也觉得UI很重要,不过别人没有作出好的UI的时候,我就觉得好像做好的UI是一件很难的事情,现在才发现其实没有什么做不到的,比如最近的HTC钻石以及HTC的Google手机的Sense系列的UI就可以发现,其实UI可以做的好看一点。所以我也开始尝试在手机上面做一点UI方面的研究,也算是尝试尝试把。
在研究了MSDN的UI Framework以及一些其他的UI开发者开发的UI的代码后,觉得其实UI开发还是很麻烦,性能也是一个问题,而且封装也是个问题,其实WM的这里的封装不是很好封装,而且也不能保证所有的开发都能够使用自己封装的类。所以授人以鱼不如授人以与授人以鱼不如授人以渔,首先先上图。


其中1图为初始界面,2图(右上)为手势操作,用户可以拖动ImageButton,3图为半透明效果,4图为PNG绘制半透明效果,背景字体也可以看见。
同时,这里解决的问题有:
1.绘制透明背景层的PNG图片,而不是BMP,并且消除锯齿。
2.自定义标题栏并且能够自定义高度和执行渐变。
3.自定义半透明的菜单,这里可以参考UI Framework。
因为代码比较复杂,所以我会在后面的文章中讲解如何自己编写一个UI Framework以及事件响应等一些步骤,如果是高手就可以略过了。
JSON是什么?我想JSON可能对很多人来说都不陌生了吧,前面我们说到可以用最原始的方法读取XML,又可以在一切都规范的情况下读取XML,那么我们有没有更好的数据读取方式呢,当然有,就是JSON,说实话我原来没怎么去接触JSON,不过最近看了一下JSON的东西,觉得JSON真是太简单了。真是不用不知道,一用吓一跳,没想到还有这么轻量的东西。
多的不说了,我们先看一下JavaScript怎么读取JSON数据的。
var myJSONObject = {"bindings": [
{"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"},
{"ircEvent": "PRIVMSG", "method": "deleteURI", "regex": "^delete.*"},
{"ircEvent": "PRIVMSG", "method": "randomURI", "regex": "^random.*"}
]
};
我们可以看到上面的代码,是不是感觉有点乱?嗯,是有一点,不过其实当你了解之后就会觉得其实很整齐了。我们现在这里可以读取randomURI这个数据,怎么读呢,看看下面的代码。
myJSONObject.bindings[2].method
这个代码是不是很简单?其中,ircEvent可以看做字段,PRIVMSG可以看做值。其实JSON是基于map实现的,所以也是键值对应的了。这样看上去是不是就不那么乱了?OK,既然我们了解了JSON的基本原理后,一切都好办了,既然我们有一个这么好的数据源,我们就可以轻松的读取远程数据了,其实代码很好写,我们一样是获取远程的responseText,然后转换成JSON数据就可以了,示例代码如下。
function LoadDone(url)
{
if (req.readyState == 4)
{
if (req.status == 200)
{
response = req.responseText;
var json = eval(‘(‘ + response + ‘)‘);
//{"weather:{"city":"北京"}……"}
var city = json.weather.city;
//插入我们的json数据
$("#city").append(city);
$("#load").hide("slow");
}
else
{
//connect failure
}
return response;
}
}
上面的代码是基于这篇文章写的,这篇文章和读取JSON差不多,也是一开始读取远程数据,获取response对象。最开始是获取responseText,上一篇文章是responseXML,这里我们还是读取responseText,然后转换为JSON对象,这里就要注意转换的方式,是不能够直接用responseText的,直接用是会发生错误的。
OK,既然我们远程可以读取JSON数据了,我们也可以使用现有的很多网络提供的Service做很多事情了,比如做一些IP查询啊,股票查询,天气查询的事情了,比如我这里,就简单的做了一个小插件。:),还在Alpha阶段。


所以说读取远程数据在Windows Mobile 6.5 Widget中是非常重要的,这里我说了3种读取远程数据的方式,都是非常行之有效的,所以有了远程数据,再加上HTML和JavaScript,就具有非常强的可扩展性了,可是在开发和维护上,暂时还没有很好的解决方案,不过我觉得这么轻量的东西,不需要搞那么复杂。
前面我的一篇文章,即WM6.5读取远程数据,其中讲到XMLHttpRequest有时候并不能读取到数据,这一定程度上是正确的,因为不同的网页,不同的规格的XML,可能通过XMLHttpRequest获取的数据为空(例如我的博客的RSS就读不到),这得看浏览器和网站之间的彼此的兼容性了,当然,XMLHttpRequest在某种程度上还是非常好用的,因为它的responseXML对象能够很好的为我们读取数据。所以今天我们用XMLHttpRequest读取数据。
这几天和几个WM的开发人员聊了一下,有的人也说XMLHttpRequest这个在Widget开发里并不好用,确实不是很好用,但是偶尔还是很好用的。比如在你正确的编写了一个XML的时候。所以这里可以看的出来,我们平时遵守标准是多么重要的一件事情啊。如果不遵守标准,很多时候做事情就变得更加复杂了。。。废话太多了,我们先做一个简单的RSS阅读器,我们先看效果图。


这里我们使用了JQuery混合使用,可真是网页开发一个都不能少啊。(右边的这个图是直接读取XML里面的description,所以排的很混乱,如果是自己做的话,就会更好看了,我这是读的Amazon的数据)
首先我们先写好我们的HTML,代码如下所示。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Shang RSS Reader</title>
<script src="js/widget.js" type="text/javascript"></script>
<script src="js/menu.js" type="text/javascript"></script>
<link href="css/css.css" rel="stylesheet" type="text/css" />
<script src="js/jquery-1.3.2.min.js" type="text/javascript"></script>
</head>
<body onload=
"load(‘http://www.amazon.com/rss/bestsellers/books/ref=pd_ts_rss_link’,'true’)">
<div class="load" id="load">
<img src="images/load.gif" />
<br />
loading..
</div>
<div id="root">
<div class="main" id="main">
</div>
<div class="close" id ="close"
onclick="CloseRead()" style="display:none;">close</div>
<div class="main" id="detailRead">
</div>
</div>
</body>
</html>
我们可以看到在页面加载的时候,我们启用了load方法,load方法就是执行远程的数据的连接,这里我们就是读取数据,读取数据代码如下所示。
function load(name,isMain)
{
var loadText = StartLoad(name,isMain);
return loadText;
}
var response;
function StartLoad(url,isMain)
{
var returnValue;
if (window.XMLHttpRequest)
{
req = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
req = new ActiveXObject("Microsoft.XMLHTTP");
}
if (req != undefined)
{
req.onreadystatechange = function()
{
returnValue = LoadDone(url,isMain);
};
req.open("GET", url, true);
req.send("");
}
return returnValue;
}
function LoadDone(url,isMain)
{
if (req.readyState == 4)
{
if (req.status == 200)
{
response = req.responseXML;
if(isMain)
{
CreateElement(req.responseXML);
}
$("#load").hide("slow");
}
else
{
//connect failure
}
return response;
}
}
这里我们就是读取远程数据的几个函数了,同时还要注意上面我加红的代码。这里如果读取成功的话,我们就创建元素,例如这里创建的就是一些div了。isMain参数是我自己加的一些扩展用的参数,所以这里可以暂时不用理解。我们看到前面的HTML我写的也是true,所以这里面所有的isMain都是true。CreateElement方法就是创建前面样式的一些标题,这样可以让用户读到RSS数据,示例代码如下所示。
function CreateElement(responseXML)
{
var title = GetElementByXML(‘title‘,responseXML);
var link = GetElementByXML(‘link‘,responseXML);
for(tempNum = 1; tempNum < title.length; tempNum++)
{
var divs = ‘<div id=\’detail‘ + tempNum + ‘\’ class=\’detail\’
onmouseover=\’Change(this.id)\’
onmouseout=\’ReturnDiv(this.id)\’
onclick=\’ShowDetail(this.id)\’>‘ + title[tempNum].firstChild.nodeValue + ‘</div>‘;
$("#main").append(divs);
}
}
上面的代码看起来可能有点乱,那是因为我为了整齐所以换了行,但是好像还是有点乱,=。=!,不过上面的代码就是从1开始创建div,然后附加到main里面。为什么是从1呢,因为第0个元素往往都是XML最开始的标题,例如RSS的标题啊之类的,所以从1开始就是最开始的标题和内容了。
剩下的代码就是补全我们的RSS阅读器中点击每一个元素的操作了,就是实现上面的onmouseover,onmouseout,onclick等方法,这里我就写一下onclick方法吧,我觉得这个方法还是比较重要的,其他的可以在源代码中去看。
function ShowDetail(id)
{
var idNumber = id.toString().replace("detail","");
//获取description元素
var description = GetElementByXML(‘description‘,response);
//隐藏主窗体
$("#main").hide("slow");
$("#close").show("slow");
//显示文章
$("#detailRead").append(description[idNumber].firstChild.nodeValue);
$("#detailRead").show("slow");
}
当我们单击【close】的时候,所作的操作和这里相反就行了。
小结
这样,一个简单的RSS阅读器就做好了,也让我们深入的了解了Windows Mobile 6.5如何使用XMLHttpRequest来读取数据,读取远程数据是非常重要的,因为很多时候我们可以将配置和数据保存在远程文件中,或者在远程配置一个WebService,然后在客户端进行调用。但是在这里,还得注意你的XML文件格式的正确性,否则无法用这种方法进行调用,而只能用原始的方法读取数据,这样也是非常不好的。
这里我也只是抛砖引玉,代码不是很复杂,希望能对初学者有一定的帮助。
rss.wgt (126.26 kb)
我想这应该是Windows Mobile 6.5 Widget这个系列的一篇比较无聊的文章了吧,当然是可能,:)。不过如果等Windows Mobile 6.5 Widget正式出炉了之后,肯定会再继续写更深入的,因为Windows Mobile 6.5 Widget暂时来说还只是测试的,我觉得基本上现在Windows Mobile 6.5 Widget连测试都算不上,另一方面,Windows Mobile 6.5 Widget需要的一些技术也是比较新和比较复杂的,除非你能很好的控制Windows Mobile 6.5 Widget里面的JavaScript和Windows Mobile 6.5 Widget的引擎,否则还是用微软自己的东西开发比较方便,比如Entilty Framework,比如ADO.NET Data Service,如果你C#不太懂的话,Windows Mobile 6.5 Widget还是开发起来有点麻烦的,首先我要承认一点,前面我说的Widget很简单,是有失偏颇的,首先在开发来说是很简单,你用HTML和CSS就能开发了,还能用一下JS的类库来做做效果,但是其实也有复杂的一面,也是今天这篇属于收尾的性质的文章要讲的。
什么能做什么不能做?这个问题问得好,在我写第一篇文章的时候就想过这个问题,不过当时实在是太冲动了,拿到了Widget,安上了模拟器运行了一个HELLO WORLD就觉得Widget是天下无敌了,其实后来才发现不是的,什么能做什么不能做?比如JQuery吧,JQuery能在Widget里面运行吗,答案是有一些可以,而有一些不行,比如JQuery里面最常用的函数$("#id").show(),是可以用的,但是你要用$get(url)方法的话,就不知道哪里出错了,我也坦白我调试了这个东西调试了3-4个小时,要不然也不会有前面的Widget读取XML这篇看似简单的文章了。
另外一个可能不能做的事情就是JavaScript,这里我为什么要说可能呢,Widget不就是HTML和JavaScript组合在一起的吗,OK,是的,而且仅仅是HTML和JavaScript才能构成Widget。那么为什么又“可能”呢,OK,在用JavaScript的时候,要注意JavaScript的版本,否则的话方法也不一定运用的了哦,比如XMLHttpRequest方法返回的responseXML就有可能是null,这很有可能和移动平台的浏览器的认证和安全有关。所以并不要那么自信所有的事情都能做。
不过好在微软在Windows Mobile 6.5 Developer Tool Kit里面已经发布了一个样例,就是搜索组件,可以看一下源代码,是如何操作的。


从上面我们就可以看到微软的这个小组件看上去还是很不错的,如果想知道到底什么可以做什么不能做的话,可以仔细的看看他们的代码。另外一方面值得一说的是,有很多人会说,WM的用户都喜欢在各大网站去找软件下载,所以说微软的商店也不会很成功,所以这里值得一提的是,在做Widget开发的时候,真实的WM6.5是不会从拷贝的wgt文件中运行安装的,也就是说如果你拷贝一个wgt到手机里,根本不能运行,我想这也就是微软的一个在线商店的策略吧。
剩下要说的,就是如果要测试JavaScript并让你的代码更好懂的话,建议去这个网站。另外,搜索Widget并不是样例也不是可分发的软件,建议还是看看,学习为好。:)
这两天一直在寻找Windows Mobile 6.5 Widget如何进行数据访问,前面的一篇文章我说了可以使用XML作为数据交换进行远程的数据存储,当然Widget只是轻量级的东西,如果做的很复杂的话就不好了,所以今天这里我就说一下如何使用AJAX4,ADO.NET Data Service和Entity Framework进行数据访问,我估计大家看这个都会觉得有点头晕,没错,我头也晕,今天和国外的一个WM MVP讨论了一下这个事情,觉得这个让一个本来轻量的Widget变得更加复杂了,如果是XML的话,会简单很多,但是速度我很难保证。。
好了,话不多说,和朋友讨论之后就把他的文章直接翻译过来,当然,如果你有条件的话本地制作也是可以的,因为我本身没有Entiry Framework并且也安装不了,不过我运行了代码之后是完全可以运行的,所以说理论上没有任何问题。最后题外一下,微软发布东西可真够勤奋的,弄的我们开发人员很累,而且这些东西还不是最好用的。这里提醒一下,这里所用的几个技术现在还都是Preview版本,以后有什么更改我可不敢保证。
我们首先需要创建一个项目,我们可以使用VS进行项目的创建并删除掉Web.config和Default.aspx,因为这些是不需要的,然后我们可以创建一个基本的WM 6.5 Widget结构,如果你现在还不会,可以看看这篇文章,基础的讲解Windows Mobile 6.5 Widget的组成结构,OK,现在如果我们创建好了结构之后,就是创建数据了。
现在我们创建一个Entity Data Model以便和数据进行互动,选择添加新项,然后选择【ADO.NET Entity Data Model】,然后这里我们给他命名为AdventureWorksModel.edmx。通过Entity Data Model向导,特别是数据库连接,当创建完成后,选择Produce和ProductCategory两张表,其他的我们可以不用管,如果选择好了之后我们就可以看到下图了。

当我们做完了之后我们就要创建一个ADO.NET Data Service模板,这里我们创建一个名为AdventureWorksData.svc的模板。当我们做完了之后我们就要创建一个ADO.NET Data Service模板,这里我们创建一个名为AdventureWorksData.svc的模板。一旦项目被添加上去了我们就可以从中间获取我们想要的数据,下面代码中间红色部分就是用于更新AdventureWorksLTEntities数据模型的。
public class AdventureWorksData : DataService<AdventureWorksLTEntities>
{
// This method is called only once to initialize service-wide policies.
public static void InitializeService(IDataServiceConfiguration config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.All);
}
}
搞定之后我们就需要在我们的项目中添加AJAX4了,我们可以直接下载AJAX4并放到我们的项目路径钟,因为AJAX是文件,所以我们可以下载的AJAX4是可以看到源代码的。:),我们可以放到如下图所示的地方。

然后我们的插件页面就是一个很简单的页面,注意前面我也写过,Windows Mobile 6.5是不能够支持ASP.NET页面的,如果真的要让我们的插件能够在ASP.NET下面运行就相当于在移动设备上安装一个ASP.NET服务器。。。所以我们的插件只能够包含HTML,CSS和JavaScript。我们可以直接创建一个HTML进行插件的内容编写。
OK,我们可以开始编写HTML了,我们的这个页面并没有任何一点的JS代码因为我们的JS代码全部包含在AJAX4库中了。示例代码如下所示。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>AdventureWorks – Products</title>
<style type="text/css">
.sys-template {display: none;}
.rowSelected {background-color: yellow;}
</style>
<script src="MicrosoftAjax/MicrosoftAjax.debug.js" type="text/javascript"></script>
<script src="MicrosoftAjax/MicrosoftAjaxTemplates.debug.js" type="text/javascript"></script>
<script src="MicrosoftAjax/MicrosoftAjaxAdoNet.debug.js" type="text/javascript"></script>
</head>
<body xmlns:sys="BLOCKED SCRIPTSys"
xmlns:dataview="BLOCKED SCRIPTSys.UI.DataView"
xmlns:datacontext="BLOCKED SCRIPTSys.Data.AdoNetDataContext"
sys:activate="*">
<table
sys:attach="datacontext"
datacontext:sys-key="dataContext"
datacontext:serviceuri ="http://192.168.0.102:18886/AdventureWorksData.svc"
>
<thead>
<tr>
<th>Select Category</th>
</tr>
</thead>
<tbody
id="dvCategories"
class="sys-template"
sys:attach="dataview"
dataview:sys-key="categoriesKey"
dataview:dataprovider="{{ dataContext }}"
dataview:autofetch="true"
dataview:selecteditemclass="rowSelected"
dataview:fetchoperation="ProductCategories"
dataview:fetchparameters="{{ {$expand: ‘Products’} }}"
>
<tr sys:command="select">
<td>{{ Name }}</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>Name</th>
</tr>
</thead>
<tbody
class="sys-template"
sys:attach="dataview"
dataview:sys-key="moviesKey"
dataview:data="{binding selectedData.Products, source={{categoriesKey}} }">
<tr>
<td>{binding Name}</td>
</tr>
</tbody>
</table>
</body>
</html>
上面是一个ADO.NET Data Service模板,这个模板通过AJAX4和我们的Service进行连接,编写完成后我们就可以编写config文件了,示例代码如下所示。
<?xml version="1.0" encoding="utf-8" ?>
<widget xmlns="http://www.w3.org/ns/widgets"
id="http://www.builttoroam.com/ProductWidget"
version="1.0">
<name>AdventureWorks Product Widget</name>
<description>
Basic product widget based on ajax 4
</description>
<author href="http://www.jguoer.com"
email="soundbbg@live.cn">
Guo Jing and Nick Randolph @ Built To Roam
</author>
<content src="Products.htm" type="text/html"/>
<access network="true"/>
<icon src="BTRLogo.png" />
<license>
here is the license
</license>
</widget>
我们编写完成后就需要打包我们的程序了,打包直接用zip然后修改后缀为wgt即可,然后我们就可以放在我们的设备中用了。然后可以在设备中打开我们的项目,这里我偷懒,还是叫JQuery,可以看到他是不会更新并覆盖原来的程序的。


我们可以看到我们的程序已经正确运行了。
不过我觉得,这样做真的很复杂,开发复杂不说(其实本来HTML和CSS就能够很简单的),然后还需要远程服务,还需要是.NET 3.5 SP1,这在国内的,从主机上是很不好找的,然后在host这方面,也不是很好办,毕竟国内这方面的东西不是很多,对新事物的接受能力也没有国外强。在这里感谢国外有人MVP的指导,在和他探讨中了解了更多关于Widget方面的开发。原文如此。
前面我们制作了几个简单的Windows Mobile 6.5 Widget,但是这还不够,如果要做一个强大的Windows Mobile 6.5 Widget,我们势必要连接数据源进行数据的显示,我昨天晚上研究这个问题研究到3点多还没研究清楚,今天又想了半天,还直接加了WM Team的人询问了情况,可以说,暂时Windows Mobile 6.5 Widget还不够那么强大,不过我们可以用折中的方法获取数据,就是读取XML,读取XML是一个非常不错的选择,因为大部分的数据交换都能用XML描述。当然,在客户端浏览器上读取XML时非常简单的一件事,但是是否在Widget这个引擎中读取也一样是一件简单的事情呢。
其实,在思路上差不多,但是有些细节要注意。我们可以使用XMLHttpRequest对象获取远程服务器上的文本,然后再进行转换,值得注意的是,这里暂时不支持XMLDom,所以我们只能用正则表达式的形式获取XML的数据了。我们先写文本内容,代码如下所示。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Default Page</title>
<link href="css/css.css" rel="stylesheet" type="text/css" />
<script src="lib/jquery-1.3.2.min.js" type="text/javascript"></script>
<script src="lib/httprequest.js" type="text/javascript"></script>
</head>
<body>
<div id="mother"></div>
</body>
</html>
我们用的是一个非常非常简单的页面,这个页面使用了JQuery和我们自己写的类,另外说明一下,用JQuery的$.get方法好像并不能够获取到远程的XML数据,并且获取的数据获取的responseXML也很有可能为null,所以我们只好用最原始的方法获取数据。其中httprequest代码如下所示。
function CheckHttpRequest(url)
{
//check the httprequest and get the request from the url
var text;
var req=new XMLHttpRequest();
req.open("GET", url, false);
req.send(null);
if(req.status==200)
{
text = req.responseText;
}
else
{
text = "";
}
return text;
}
上面的代码就是获取一个url的内容,我们获取XML或RSS都行,反正用正则表达式获取的。其中我们还需要使用一个方法,这个方法就是获取XML的标记,由于这里用不了XMLDom,所以只能用正则,示例代码如下所示。
function GetElement(ele,text)
{
var reg = new RegExp("<"+ele+">.*<\/"+ele+">","g");
var show=text.match(reg);
//replace the element
for(i=0;i<show.length;i++)
{
show[i] = show[i].replace("<"+ele+">","").replace("</"+ele+">","");
}
//return now array
return show;
}
上面的代码也非常简单,就是从文本中找到字符并替换掉标记,上面两个方法都是在我们的httprequest类中的,我们保存之后再直接在我们的html里面编写即可,html里面的script代码如下所示。
$(document).ready(function(){
try{
var t = CheckHttpRequest("http://www.jguoer.com/syndication.axd");
var title = GetElement(‘title‘,t);
var link = GetElement(‘link‘,t);
for(i=1;i<link.length;i++)
{
var divs = "<div style=’border-bottom:1px solid
#ccc;background:#fafafa;padding:5px;’>"+title[i]+"</div>";
$("#mother").append(divs);
}
}
catch(e)
{
var divs = "<div style=’border-bottom:1px solid #ccc;
background:#fafafa;padding:5px;color:red’>Error Happend!</div>";
$("#mother").append(divs);
}
});
这样我们一个读取远程数据的widget就制作好了,同样打包并运行,运行结果如下图。


这里URL是填写的我的博客的RSS数据,这里我们看到的也是我的博客的RSS数据,说明我们的RSS读取成功了。
不过这里有一个很大的缺点,就是加载的时候速度有点慢,这对应用程序来说可以说致命伤,所以基础好的可以在页面上再加上一个loading界面,这样就看上去更加有好一点。不过可以说,WM的Widget还需要有很多要做。另一种方式就是使用AJAX 4和ADO.NET Entity进行数据访问,不知道国内有多少人用.NET 3.5 SP1并有主机,看来在中国是不太现实的啊。明天我有可能翻译一个国外WM友人的一篇文章,如何使用AJAX 4和ADO.NET Entity进行数据访问。
Windows Mobile 6.5 Widget可以使用我们通常最会使用的东西,如HTML,JavaScript,CSS等等进行富应用程序的开发,提高用户体验,还可以使用AJAX进行插件的开发,对于熟悉JQuery的人,当然也可以使用JQuery进行开发,不过在Windows Mobile系统钟,对于JQuery这种再次封装的框架的性能,不是很好,就连我的当前的WM机皇都感觉特效有点卡卡的,比如show("slow")这样,还是不是很好。
当然Windows Mobile 6.5 Widget对AJAX的支持已经很不错了,如果使用的是AJAX 4的话,应该很不错,我没试过,国外的一些博客尝试使用AJAX 4,而且是VS2010,而国内的VS2008用的比较多吧,所以就暂时先不尝这个鲜,而且JQuery也支持AJAX,还能够很好的移植,干嘛非要用AJAX4呢。
言归正传,我们制作一个Widget的时候(前面说了基于浏览器的),而Windows Mobile 6.5本身有一个引擎可以很好的解释我们的Widget,但是本身如果要控制Windows Mobile 6.5 Widget的窗口的话,似乎还需要hook一下。但是这里微软已经有一个引擎可以使用了。可以看下图。(其中JQuery没用)

我们可以看到,左边是默认的情况下,左边的软键盘是退出按钮,右侧的菜单里面也只有退出,而在右边的图片里面我们自定义了一个Click Me按钮,而我说了微软提供了引擎去为我们hook一下窗口,这怎么写呢,可以看下面的代码。
<head>
<title>Default Page</title>
<link href="css/css.css" rel="stylesheet" type="text/css" />
<script src="lib/jquery-1.3.2.min.js" type="text/javascript"></script>
<script type="text/javascript">
function clickMeHandler() {
alert("do something");
}
function cradled()
{
//创建一个menu对象
var menu = widget.menu;
//使用id创建一个MenuItem
var menu1001 = menu.createMenuItem(1001);
//设置menu对象的属性
menu1001.text = "Click Me";
menu1001.onSelect = clickMeHandler;
//将MenuItem附加到Menu里面
menu.setSoftKey(menu1001, menu.leftSoftKeyIndex);
}
</script>
</head>
<body onload="return cradled()">
This is a test page which crate a menu item in the widget!
</body>
上面的代码我已经注释了,通过上面的代码,我们就能够在Windows Mobile 6.5 Widget创建一个自定义的Menu了。但是这个时候你会想,为什么我只能创建在左侧,而右侧的菜单栏中还没有出现呢,如果要在右边的菜单栏出现,我们就需要添加到右侧,只用使用下面的代码即可。
//附加到最后
menu.append(menu1001);
这样我们就可以添加相应的菜单并添加相应的事件响应了,运行效果如下图所示。

这样我们不用C/C++之类的东西就能够创建一个富应用程序最基本的程序了,如果你需要使用数据库还有调用本地的DLL的话,很复杂,不是不可能,不过要等我学会了之后才能写,:)。现在看上去还是比较复杂的。另外,今天下了WM6 SDK,发现用C++写的WIN32,MFC,ATL的东西有点小复杂,并且实用价值不大,比如更改一下窗口啊,绘制一下图片啊之类的,而用C#呢,做的就更少了,只能管理一下联系人,发一下短信,打一下电话什么的,哎,不知道手机开发的前景到底在什么应用上。小迷茫中。。
代码下载
test.wgt (65.34 kb)
我们上面知道了Windows Mobile 6.5的Widget还是小有潜力的,而且也很方便制作,那么我们的Widget还能干嘛呢,既然是HTML,是不是也有DOM对象,也能够使用JavaScript呢?按道理来说,既然Windows Mobile 6.5 Widget是使用网页的形式去制作的,那么Windows Mobile 6.5就有一个专门针对Widget的engine,所以Windows Mobile 6.5 Widget应该可以使用JavaScript,想到什么就去做,这是我的一个习惯,管他的,先做了再说。
同样我们创建一个文件夹,很简单,就是放一些源代码,我猜想Windows Mobile 6.5 Widget既然是有引擎的,这个引擎肯定是和浏览器引擎差不多,所以我们做一个网站放到里面去,应该可以运行。OK,我们先来写config文件。
<?xml version="1.0" encoding="utf-8" ?>
<widget version="1.0" xmlns="http://www.w3.org/ns/widgets" id="test">
<name>JavaScript Test</name>
<content src="widget.htm" type="text/html" />
<access network="true" />
<icon src="cover.png"/>
<description>
Test JavaScript Page Widget!
</description>
</widget>
代码很简单,但是我们不要忘记了里面有些东西要定义,定义了的东西要存在。写完了config,然后再来写界面了。一个典型的HTML文档。
<html>
<head>
<title>JavaScript Widget Test</title>
<link href="css.css" rel="stylesheet" type="text/css" />
<script language="javascript" type="text/javascript">
// <!CDATA[
function Button1_onclick() {
var textBox = document.getElementById('TextArea1');
textBox.innerHTML = 'Hello JavaScript and CSS!';
alert('Hello World!');
}
// ]]>
</script>
</head>
<body>
<div class="main">
This is a javascript test widget!
</div>
<div class="content">
<textarea id="TextArea1" name="S1"></textarea><br />
<br />
<input id="Button1" type="button" value="OnClick"
onclick="return Button1_onclick()" />
</div>
</body>
</html>
在这段代码里面,我们使用了JavaScript并且获取了DOM对象并弹出窗口,这都能不能在Windows Mobile 6.5 Widget引擎里运行呢,我们同样打包一下。(记得这里的css文件自己定义啊,因为很简单所以我就不把css的代码发到上面来了)。
同样打包成后缀wgt的文件后放到移动设备文件夹中,然后运行。

我们可以看到我们的程序已经在开始菜单了,然后我们点开运行程序就可以了。

可以看到我们的JavaScript脚本已经运行了,这说明什么?这说明只要能用JavaScript做的事情,咱都可以在Widget里面做,而且还非常方便,这也就是说如果我要做一个Twitter或者Facebook的应用的话,只需要做HTML和JavaScript就行了,而且还可以使用JQuery具有更好的用户体验。而且我们也可以看到,CSS也可以使用,所以, Windows Mobile 6.5 Widget可以说很强大了。
最后再回过头来看看Windows Mobile 6.5 Widget,其引擎其实就是一个浏览器(我感觉),因为我看到了about:blank,在地址栏,那么既然是浏览器,那么能否支持ASP.NET的呢,我想细心的朋友应该也会想到,可惜,暂时Windows Mobile 6.5 Widget是不支持ASP.NET的,但是可以解析静态内容,而不能解析服务器端控件和代码,如果Windows Mobile 6.5 Widget支持ASP.NET的话,我想就更强大了。。
下载代码:
code.wgt (23.45 kb)