Main's profile我的Domain,我做主PhotosBlogListsMore Tools Help

Blog


    December 16

    你看不到我,你看不到我……

    应某牛的要求,删除本篇文章。你看不到我,你看不到我……………………

    December 09

    继续修正weather.js脚本

    我的Domain 我的Domain
    我的Domain
         自从脚本上传到远景论坛后,大家反应不错,也反映了不少错误,我自己也找到一些,今天再次看了看脚本,发现自己犯了一些低级错误,一些本应该是float类型的数据没有转换过来,还是字符串类型,导致后面的计算错误,所以不能显示晚上的月亮。现在已经把这个bug修正了。不过另外一个bug就不怎么好找了,就是设置不能保存。我现在还不能确定是什么原因,因为脚本调试比较困难,现在最好的方法就是直接修改localizedStrings.js文件里面的设置,改为自己地区的代码后,就不用每次重新启动重新设置了。
         另外也有人反映不能自动更新,这个我还没有确定,我是设置1个小时更新一次,不过就算一个小时更新一次也不一定有新的数据,如果服务器没有更新当然就不会更新了,所以这个测试起来需要有些耐心,让电脑从早到晚开着,看看早上和晚上有没有不同就知道了
         不过现在时间也不多了,可能我只会把保存问题解决掉,以后就要等很长一点时间才能在此修正了。

         原来不是不能保存,而是只能保存当前实例,如果关闭了当前Gadgets,添加一个新的,那个新的将会使用默认值,而不是上一个实例的设置!这是微软的API设置的,除非自己写一个保存的函数。我觉得这样挺好的,这样我就可以同时使用多个Gadgets,每个都使用不用的设置,互不干涉。另外也把部分字符串汉化了,但是还没有完全汉化,其实应该根据SkyCode来汉化的,不过因为SkyCode不够直观,所以也就懒得改了。最后证实是可以自动更新的。到此为止,虽然还有一些小细节有问题,不过已经不影响使用了,就这样先放下,以后有时间自己做一个Gadgets,使用中央气象台的信息更准确。不过到时微软应该已经开放了其他地区的服务了。
    我的Domain
    我的Domain 我的Domain
    December 08

    对vista中weather.js的分析

    我的Domain 我的Domain
    我的Domain
          安装好的vista一直不能用sidebar的天气预报功能,感到很不爽。经过对weather.js文件的分析,初步知道原因所在。就像前几天说的那样,是因为wlsrvc.dll文件检查到系统区域设置为中国,因此直接提示不能使用这个功能,完全没有去抓取网站。其实如果我们自己根据网址在浏览器中输入,是可以得到天气预报信息的。这样就想到了几种解决办法。
    1. 更改系统区域设置为美国等。这样可以直接使用天气预报功能,不过对中文支持有问题,这样当然不可取;
    2. 替换wlsrvc.dll文件。可以替换早期版本的,也可以自己重新写一个,不过这样会破坏这个文件的其它功能,也不可取;
    3. 修改weather.js等文件。这个就是我要做的工作。

         经过分析这个js文件,关键在下面几句中:


      try
      {  
        // Connect to Weather Service .dll
        var oMSN = new ActiveXObject("wlsrvc.WLServices");
        this.oMSN = oMSN.GetService("weather");
      }
      catch (objException)
      {
        this.isValid = false;
        this.statusMessage = getLocalizedString('ServiceNotAvailable');
        this.oMSN = new Object();
      }

     

         这里就是调用dll的地方,在这里会返回1506,就是ServiceNotAvailableInYourArea。因此需要替换掉这段代码。
         根据分析对象oMSN的使用情况,可以找到oMSN对象的成员有哪些,这样就可以自己写一个对象替换掉这个。里面最主要的是SearchByCode函数和onDataReady事件。只要把这两个写出来,基本上就可以修改成功。可惜我对JavaScript的研究不深,写出来的代码可能不好看,冗余代码也可能会多,不过能够达到效果就好。在这里,我主要是使用Microsoft.XMLDOM对象来对网站上的xml数据进行分析,然后把需要的数据放在另一个WeatherData类中。当数据都得到后,触发onDataReady事件,更新显示数据。这里面的prototype还是我刚刚学会的,主要是用来实现类似C++的虚函数功能。下面就是我添加的代码:


    function convert(degree)
    {
     return (isNaN(degree)?0:((degree - 32) / 1.8).toFixed(0));
    }

    function toChineseDay(day)
    {
     var retVal = day;
     switch(day)
     {
      case ("Sunday"):
        retVal = "星期天";
        break;
      case ("Monday"):
        retVal = "星期一";
        break;
      case ("Tuesday"):
        retVal = "星期二";
        break;
      case ("Wednesday"):
        retVal = "星期三";
        break;
      case ("Thursday"):
        retVal = "星期四";
        break;
      case ("Friday"):
        retVal = "星期五";
        break;
      case ("Saturday"):
        retVal = "星期六";
        break;
      default:
        break;
     }
     return retVal;
    }

    function toChineseString(str)
    {
     var retVal = str;
     switch (str)
     {
      case ("Clear"): case ("Fair"): case ("AM Sun"): case ("PM Sun"):
        retVal = "晴";
        break;
      case ("Cloudy"): case ("PM Clouds"): case ("AM Clouds"):
        retVal = "阴";
        break;
      case ("Mostly Cloudy"): case ("Partly Cloudy"):
        retVal = "多云";
        break;
      case ("Showers"):
        retVal = "阵雨";
        break;
      case ("Sprinkles"): case ("PM Rain"): case ("AM Rain"):
        retVal = "小雨";
        break;
      case ("Cloudy / PM Sun"): case ("Cloudy / AM Sun"):
        retVal = "阴转晴";
        break;
      case ("Showers / Clear"):
        retVal = "小雨转晴";
        break;
      case ("Scattered Flurries"):
        retVal = "分散小雪";
        break;
      case ("Not Available"):
        retVal = "没有信息";
        break;
      default:
        break;
     }
     return retVal;
    }

    function ForeCastData()
    {
     var SkyCode;
     var SkyText;
     var High;
     var Low;
     var Date;
     var Day;
    }

    function ForeCastArray(n)
    {
     for(var i = 0; i < n; i++)
     this[i] = new ForeCastData();
    }

    function WeatherData()
    {
     var RetCode = 0;
     var Latitude;
     var Longitude;
     var SkyCode;
     var RequestPending;
     var Location;
     var SkyText;
     var Temperature;
     var Attribution2;
     var Url;
     var ForeCastA = new ForeCastArray(5);
     var Count = 0;

     this.item = function(i) {
      return this;
     }
     this.makeForeCast = function(i, c, t, h, l, dt, dy) {
      ForeCastA[i].SkyCode = c;
      ForeCastA[i].SkyText = t;
      ForeCastA[i].High    = h;
      ForeCastA[i].Low     = l;
      ForeCastA[i].Date    = dt;
      ForeCastA[i].Day     = dy;
     }
     this.ForeCast = function(i) {
      return ForeCastA[i];
     }
    }

    function MSNWeather(){
     var RequestPending = false;
     var RefreshInterval = 60;
     var Celsius = true;
    }

    MSNWeather.prototype={
     SearchByCode:function(locCode){
      var self = this;
      var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
      xmlDoc.async=true;
      xmlDoc.onreadystatechange = function() {
       if (xmlDoc.readyState == 4)
       {
        if(xmlDoc.parseError.errorCode != 0)
        {

        }
        else
        {
         var wdata = new WeatherData();
         wdata.Latitude    = parseFloat(xmlDoc.selectSingleNode("/weatherdata/weather/@lat").value);
         wdata.Longitude   = parseFloat(xmlDoc.selectSingleNode("/weatherdata/weather/@long").value);
         wdata.Location    = xmlDoc.selectSingleNode("/weatherdata/weather/@weatherlocationname").value;
         wdata.Attribution = xmlDoc.selectSingleNode("/weatherdata/weather/@attribution").value;
         wdata.Attribution2= xmlDoc.selectSingleNode("/weatherdata/weather/@attribution2").value;
         wdata.Url         = xmlDoc.selectSingleNode("/weatherdata/weather/@url").value;
         wdata.SkyCode     = parseInt(xmlDoc.selectSingleNode("/weatherdata/weather/current/@skycode").value);
         wdata.SkyText     = toChineseString(xmlDoc.selectSingleNode("/weatherdata/weather/current/@skytext").value);
         wdata.Temperature = parseInt(xmlDoc.selectSingleNode("/weatherdata/weather/current/@temperature").value);
         wdata.Temperature = isNaN(wdata.Temperature)?0:wdata.Temperature;
         if (self.Celsius)
           wdata.Temperature = convert(wdata.Temperature);
         for (var i = 1; i <= 5; i++)
         {
          var node = xmlDoc.documentElement.childNodes[0].childNodes[i];
          var SkyCode = parseInt(node.getAttribute("skycodeday"));
          var SkyText = toChineseString(node.getAttribute("skytextday"));
          var High    = node.getAttribute("high");
          if (self.Celsius)
            High = convert(parseInt(High));
          var Low     = node.getAttribute("low");
          if (self.Celsius)
            Low = convert(parseInt(Low));
          var Date    = node.getAttribute("date");
          var Day     = toChineseDay(node.getAttribute("day"));
          wdata.makeForeCast(i-1, SkyCode, SkyText, High, Low, Date, Day);
         }
         wdata.RetCode = 200;
         wdata.Count = 1;
         self.OnDataReady(wdata);
        }
       }
      };
      xmlDoc.load("http://weather.service.msn.com/data.aspx?src=vista&wealocations="+locCode);
     },
     OnDataReady:function(data){}
    }

     


         然而很可惜,事情并没有到此就解决了。虽然我把这段代码单独出来是没问题的,可以得到需要的所有数据,但是放回如来的weather.js文件的时候,居然提示SearchByCode没有声明,搞得我很郁闷。只要解决这个问题,应该就可以用了。
         时间不早了,明天继续研究。

    我的Domain
    我的Domain 我的Domain