読み込んでいます...

用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)