网络电视的设计
最近整天待在实验室,实验室防火墙把关太紧,一点娱乐也没有,没办法于是把眼睛瞄上了网络电视。哪知下载下来一看是共享的,本想把它暴破了,不过试用后发现原理其实还是蛮简单的:软件只是记住了网络电视的地址,然后将其打开而已-----这样的东西也能“共享”?
软件中只是有一系列的菜单而已,点击菜单项则会打开相应的网络视频,于是我计划把菜单的内容保存在xml文件中,软件启动时再加载,这样可以方便添加电视地址。xml文件格式如下:
<item text="中央电视台">
<item text="中央一套" address="mms://61.177.180.147/cctv1" />
<item text="中央电视台_新闻台" address="mms://winmedia.cctv.com.cn/live1" />
</item>
<item text="中央一套" address="mms://61.177.180.147/cctv1" />
<item text="中央电视台_新闻台" address="mms://winmedia.cctv.com.cn/live1" />
</item>
其中,text即为菜单项中显示的标题,address则是网络视频流的地址,可以看到很多都是微软的mms协议的,则默认会用media player打开。
程序的主要内容如下,随然注释不多,但应该很容易理解:程序只是递归的读取xml文件中的内容,然后加入菜单项而已:
private void Form1_Load(object sender, EventArgs e)
{
XmlDocument doc = new XmlDocument();
//如果网络不畅的话则有可能会抛出WebException的。
doc.Load(tvListPath);
XmlElement ele = doc.DocumentElement;
XmlNodeList nodeList = ele.SelectNodes("item"); //得到一个名字为IIFF的所有节点
ConfigMainMenu(nodeList, this.menuStrip1, null);
}
//包含菜单项内容的xml文件的地址。
private const string tvListPath = @"http://uploadlist.googlepages.com/OnlineTV.xml";
private void commonToolStripMenuItem_Click(object sender, EventArgs e)
{
ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
Debug.Assert(menuItem != null);
//未set的Name取出来的将是"",所以如此进行判断
if (menuItem.Name != "")
{
Process.Start(menuItem.Name);
}
}
/// <summary>
/// 递归函数,向主窗体中加入菜单项。
/// </summary>
/// <param name="nodeList"></param>
/// <param name="menuStrip"></param>
/// <param name="menuItem"></param>
public void ConfigMainMenu(XmlNodeList nodeList, MenuStrip menuStrip, ToolStripMenuItem menuItem)
{
foreach (XmlNode node in nodeList)
{
if (node.Name == "item")
{
XmlAttributeCollection attribute = node.Attributes;
XmlAttribute text = attribute["text"];
if (text != null)
{
XmlAttribute address = attribute["address"];
//根据xml文件的内容新建一个菜单项。
ToolStripMenuItem subItem = new ToolStripMenuItem(text.Value);
if (address != null)
{
subItem.Name = address.Value;
}
subItem.Click += new EventHandler(commonToolStripMenuItem_Click);
addItem(menuStrip, menuItem, subItem);
ConfigMainMenu(node.ChildNodes, null, subItem);
}
}//如果指示为分隔符的话:
else if (node.Name == "separator")
{
ToolStripSeparator toolStripSeparator = new ToolStripSeparator();
addItem(menuStrip, menuItem, toolStripSeparator);
}
else
{
throw new InvalidDataException("节点的名称有误,请检查");
}
}
}
/// <summary>
/// menuStrip或menuItem中只能有一个是非null的,另一个则是null
/// </summary>
/// <param name="menuStrip"></param>
/// <param name="menuItem"></param>
/// <param name="item"></param>
private void addItem(MenuStrip menuStrip, ToolStripMenuItem menuItem, ToolStripItem item)
{
if (menuItem != null && menuStrip == null)
{
menuItem.DropDownItems.Add(item);
}
else if (menuStrip != null && menuItem == null)
{
menuStrip.Items.Add(item);
}
else
{
throw new NullReferenceException("menuStrip与menuItem不能全为空,亦不能全非空!");
}
}
{
XmlDocument doc = new XmlDocument();
//如果网络不畅的话则有可能会抛出WebException的。
doc.Load(tvListPath);
XmlElement ele = doc.DocumentElement;
XmlNodeList nodeList = ele.SelectNodes("item"); //得到一个名字为IIFF的所有节点
ConfigMainMenu(nodeList, this.menuStrip1, null);
}
//包含菜单项内容的xml文件的地址。
private const string tvListPath = @"http://uploadlist.googlepages.com/OnlineTV.xml";
private void commonToolStripMenuItem_Click(object sender, EventArgs e)
{
ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
Debug.Assert(menuItem != null);
//未set的Name取出来的将是"",所以如此进行判断
if (menuItem.Name != "")
{
Process.Start(menuItem.Name);
}
}
/// <summary>
/// 递归函数,向主窗体中加入菜单项。
/// </summary>
/// <param name="nodeList"></param>
/// <param name="menuStrip"></param>
/// <param name="menuItem"></param>
public void ConfigMainMenu(XmlNodeList nodeList, MenuStrip menuStrip, ToolStripMenuItem menuItem)
{
foreach (XmlNode node in nodeList)
{
if (node.Name == "item")
{
XmlAttributeCollection attribute = node.Attributes;
XmlAttribute text = attribute["text"];
if (text != null)
{
XmlAttribute address = attribute["address"];
//根据xml文件的内容新建一个菜单项。
ToolStripMenuItem subItem = new ToolStripMenuItem(text.Value);
if (address != null)
{
subItem.Name = address.Value;
}
subItem.Click += new EventHandler(commonToolStripMenuItem_Click);
addItem(menuStrip, menuItem, subItem);
ConfigMainMenu(node.ChildNodes, null, subItem);
}
}//如果指示为分隔符的话:
else if (node.Name == "separator")
{
ToolStripSeparator toolStripSeparator = new ToolStripSeparator();
addItem(menuStrip, menuItem, toolStripSeparator);
}
else
{
throw new InvalidDataException("节点的名称有误,请检查");
}
}
}
/// <summary>
/// menuStrip或menuItem中只能有一个是非null的,另一个则是null
/// </summary>
/// <param name="menuStrip"></param>
/// <param name="menuItem"></param>
/// <param name="item"></param>
private void addItem(MenuStrip menuStrip, ToolStripMenuItem menuItem, ToolStripItem item)
{
if (menuItem != null && menuStrip == null)
{
menuItem.DropDownItems.Add(item);
}
else if (menuStrip != null && menuItem == null)
{
menuStrip.Items.Add(item);
}
else
{
throw new NullReferenceException("menuStrip与menuItem不能全为空,亦不能全非空!");
}
}