Winform版微博管理工具

本文内容导读:

通过对winform微博管理工具,来记录一些容易被忽视,而且很有趣的东西,比如:

1、xslt根据xml内容生成html文档,并且里面一些比较写法注意点等

2、xslt中调用C#方法

3、xslt中引入js的一些框架

4、js调用winform后台方法及winform调用js的方法(以webbrowser为媒介)

FeedDemon这个工具基本也是js和winform的互调;

    TX的QQ广告太多,所以改用TM,之前QQ集成了腾讯微博,但改QQ为TM后,发现TM对微博的支持不太理想;但本人在中午饭后闲暇之时,喜欢看看微博和文章;但又不太喜欢每次刷网页,麻烦;本来想去网上找个PC(winform)版本的腾讯微博,结果没有,无奈,想到之前腾讯提供API了,所以去看了看腾讯微博开发平台;下面说重点,如何解决winform中对xml的解析问题;

   实现调用腾讯API的问题,在微博开发平台[http://wiki.open.t.qq.com/index.php]中可以查阅相关信息,里面有提供C#版本的SDK源文件和调用实例;所以在调用这块我不多做解释,我们只要通过API把相应的数据拿到程序里面,那么API就调用成功,剩下的就是我们程序自己内部交互的问题了;

基本上也就这么个小工具,目前支持的功能暂时只有腾讯微博,新浪微博正在准备开发中,可以支持长微博发送(大于140字自动转图片上传到腾讯微博);

我们从调用API拿到数据开始说起,因为调用API腾讯已经说的很详细,而且还有示例代码;

首先红色区域是一个webBrowser控件其他的都是winform里面的常用控件;大致实现如下

1、 首先通过API拿到xml数据,并且保存为本地的xml

View Code
statuses st = new statuses(oauthKey, "xml");
string ret = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>";
ret += st.home_timeline(0, 0, 20);
//保存为本地xml
File.Delete(path + "\\temp.xml");
FileStream fs = new FileStream("temp.xml", FileMode.OpenOrCreate);
StreamWriter sw = new StreamWriter(fs);
sw.Write(ret);
sw.Close();
fs.Close();

2、 现在API取数基本就完了,剩下的就是我们解析这个xml了并展示数据的问题了,我们使用xslt来解析xml为html文件

    a、 先看cs文件中将用xslt解析xml文件为html的代码

View Code
string path = Application.StartupPath;
XslCompiledTransform trans = new XslCompiledTransform();
trans.Load("temp.xslt");
trans.Transform("temp.xml", "temp.html");
path = path + "\\temp.html";
wbContent.Visible = true;
if (wbContent.Url == null)
{
    wbContent.Url = new Uri(path);
}
wbContent.Refresh();

     b、 然后就是temp.xslt这个文件了;鄙人之前写过一个简单的xslt解析的简单文章[http://www.cnblogs.com/RegicideGod/archive/2012/08/07/2627436.html],我们此处也用xslt来解析xml;看来前面的文件,这里的具体我也不全部放代码来;直接说问题和解决方法吧;

腾讯提供的xml中的时间是时间戳,就是C#中[DateTime.Now.Ticks]的这个东西,我们在xslt中如何将时间戳转换为时间?在网上搜了下代码(网上有相关代码,写的不太详细或不全),需要修改下cs文件中,加载xstl时候的参数设置,就是a步中修改为

View Code
StringBuilder sbXml = new StringBuilder();
StringWriter stringWriter = new StringWriter(sbXml);
XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter);

//设置可以执行脚本函数
XsltSettings settings = new XsltSettings();
settings.EnableDocumentFunction = true;
settings.EnableScript = true;

//设置xslt可以包含外部的xslt文件
XmlUrlResolver resolver = new XmlUrlResolver();
resolver.Credentials = System.Net.CredentialCache.DefaultCredentials;
string path = Application.StartupPath;
XslCompiledTransform trans = new XslCompiledTransform();
trans.Load("temp.xslt", settings, resolver);
trans.Transform("temp.xml", "temp.html");

path = path + "\\temp.html";
wbContent.Visible = true;
if (wbContent.Url == null)
{
     wbContent.Url = new Uri(path);
}
wbContent.Refresh();

然后在XSLT的头部这么写

View Code
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:csfun="urn:csharp-functions" exclude-result-prefixes="msxsl">

  <xsl:output method="html" indent="yes"/>
  <xsl:include href="fun.xslt"/>

大致的意思是让xslt文件可以调用csharp-function

然后fun.xslt中就可以这么来写,将xml中的时间戳在xslt中调用C#方法来转换成时间了

View Code
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:csfun="urn:csharp-functions" exclude-result-prefixes="msxsl">
  <msxsl:script implements-prefix="csfun" language="C#">
    <![CDATA[        
         public string CheckDate(string tm)
         {
            string timeStamp = tm;
            DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            long lTime = long.Parse(timeStamp + "0000000");
            TimeSpan toNow = new TimeSpan(lTime);
            DateTime dtResult = dtStart.Add(toNow);
            return dtResult.ToString();
         }
         ]]>
  </msxsl:script>
</xsl:stylesheet>

在来看下调用CheckDate方法

  “发表时间: <xsl:value-ofselect="csfun:CheckDate(timestamp)"/>”

就可以将xml中timestamp的值传到刚才的c#方法中,然后接收返回值了;网上还有一些代码是传到JS中处理,好像大多数都没提到要设置XsltSettings可以执行脚本函数

我们也一定要设置b步骤中的加载xslt转换xml为html的方法;

还有一个小问题是xslt中写img标签和a标签

View Code
<xsl:if test="image!=''">
              <a target="_blank" style="color:#999;">
                <xsl:attribute name="href">
                  <xsl:value-of select="image"/>/2000
                </xsl:attribute>
                <img src="{image}/120" border="0" />
              </a>
</xsl:if>

Img标签中src可以直接指定xml的image值就可以了;不用xsl:value-of来查找了;腾讯微博中,图片只给了路径,没有给图片大小,需要自己手动填写,/120是尺寸为120大小的图片/2000一般是指原图

   以上代码就可以实现基本的从微博拿到数据存储为xml在通过xslt转成html显示到webbrowser上面,就完成了整个微博的内容显示,但最重要的是需要有交互,就是对某一条微博进行评论和回复;每一个条微博右下角都会对应一个转播,评论,密语等功能操作,因为我们要通过生成的html中获取选中的那一条的微博信息,然后弹出一个提示框,让用户输入文字信息,进行评论;

这个界面(比较龊的界面)就是点击某一条微博的时候,弹出一个层的效果,然后输入文字信息点确定后,就会调用后台方法,通过API提交到腾讯服务器;

下面接说问题,在xslt模板生成的html中,是没有生成头标签的,但是我们这个地方用了一个基于jquery弹出层框架,需要导入jquery框架等,所以需要在html头部生一个标签就是经常看到容易被忽略的

<!DOCTYPE html>

虽然我们写的是html,但是我们要指定这个文档是html才行,不然webbrowser显示html带引入js时会报错,在xslt模板中我们导入上面一句话的写法是

 <xsl:template name="DOCTYPE">
    <![CDATA[<!DOCTYPE html>]]>
  </xsl:template>

然后在<html>的上面写上这么一句话,就相当于写了<!DOCTYPE html>这个东西

<xsl:value-of select="document('')/*/xsl:template[@name='DOCTYPE']/node()" disable-output-escaping="yes"/>

JS的引入问题解决了,剩下的就是点击页面的确定把html页面上的内容传到form窗体上面,那么现在的问题就是js调用winform方法,在bs开发中js调用后台方法,就是ajax但这里不行,没有IIS服务器的配合,行不通;继续百度加谷歌,发现webbrowser给我们提供了便利,就是可以让在webbrowser中的html通过js调用winform中的后台方法;我们来看下吧

a、指定主窗体类可以让webbrowser回调窗体中的方法

View Code
//指定js可以回调webBrowser中的方法
    [System.Runtime.InteropServices.ComVisibleAttribute(true)]
    public partial class FrmMain : Form
    {
        public FrmMain()
        {}
         private void frmMain_Load(object sender, EventArgs e)
        {
           wbContent.ObjectForScripting = this;  //wbContent为webBrowser控件
        }
}

b、在窗体中写好评论一条微博的方法

View Code
//评论一条微博
        public void Comments(string conText, string reid,string flag)
        {
            conText = conText == "" ? " " : conText;
            t tw = new t(oauthKey, "xml");
            string ret = tw.comment(conText, "", "", "", reid);
            if ("true".Equals(flag.ToLower())) 
            {
                BroadCast(conText, reid);
            }
        }

c、在js中的调用如下

View Code
//评论一条微博
        function Comments(reid)
         {
     
             //alert(conText);
            var con='<div style="width:'+(_iwid*0.7+25)+'px;height:'+_ihei*0.5+'px;margin-left:-8px;margin-top:-5px;">';
            con+='<textarea cols="80" style="margin-left:5px;margin-top:-5px;" rows="6" id="sendContent"></textarea><br/>您将评论:<br/>'+conText;
            con+='<br/><input type="checkbox" id="ch">一并转播';
            con+='</div>';
         
         
           $.dialog({
            width:_iwid*0.7,
            height:_ihei*0.5,
            lock: true,
            title:'评论',
            background: '#DCE2F1', /* 背景色 默认的遮罩背景色为:#DCE2F1浅蓝护眼色 */
            opacity: 0.5,       /* 透明度 */
            content: con,
            ok: function () {
            window.external.Comments($("#sendContent").val()+" ",reid,$("#ch")[0].checked);
             return true;
            },
            cancel: true
            });
         }

最重要的是标红的那句话,是在js中调用winform后台的Comments方法,并且把参数传到后台,今天消息处理;

当然还有在winform中通过webbrowser来调用js方法

//调用JS
        private void btnAddFace_Click(object sender, EventArgs e)
        {
            wbContent.Document.InvokeScript("scriptFunc", new String[] { "这是winform调用脚本方法" });
        }

到这里基本就完成了,主要是通过业务来讲解一些简单的技术问题;这些东西并不是很难理解,只是容易被忽视;

posted @ 2012-08-08 11:05  RegicideGod  阅读(2163)  评论(11编辑  收藏  举报