播放服务器端的视频

    

图2-4 自定义的Silverlight视频播放器

       这个实例设计了1个自定义的Silverlight视频播放器(视频源文件放在服务器端),如图2-4所示,这个示例完全在Expression Blend 4中设计,视频放在服务器端的文件夹中,网上调试成功。示例设计的复杂一点,当然功能也强,如果减少功能程序也会简单。图2-4上方是视频播放控件MediaElement(me);下方是需要播放的视频图片,点击可以选择视频源;中间有1个视频播放控制面板,Silverlight视频控件MediaElement有边下载边播放的功能,图2-5中间有个播放进度条,同时显示下载进度和播放进度;进度条上方的2个文本分别显示下载缓冲比例和播放器的当前状态,进度条下方的文本框显示视频播放的时间进度值;进度条上方右侧有1个三角形音量控制图标,点击就可以选择音量,喇叭图标是“静音”控制图标,点击1次变化1次,静音时喇叭图标上出现1个红色“×”;

 

图2-5 自定义的Silverlight视频播放器控制板

    当鼠标悬浮在进度条上时,先出现文本(Callout控件)显示,显示进度条当前值对应的视频时间,只要鼠标悬浮不动就会出现1个视频预览窗口(也是MediaElement控件,名为preview),可以看到此时对应的视频画面(反复播放当前画面2秒,仅几帧);进度条下方有“暂停”、“播放”、“停止”、“重播”和“全屏”等控制图标。下面说明设计过程。

1、界面设计

    新建1个“Silverlight应用程序+网站”项目,名称为SilverlightMediaPlayer,设置界面对中:改变“LayoutRoot”的布局类型为“ScrollViewer”,放入Canvas(canvas1),设置其背景和大小,设置“UserControl”的Width和Height属性为自动。

2、me控件属性设置

    “布局”中Width:448   Height:252,相当于16:9。

    “媒体”中Stretch:UniformToFill。me控件放置在Canvas布局控件canvas1中,这对me的位置和尺寸变化很重要。

3、音量控制设置

    图2-5右侧的音量控制图标表面看是三角形的,实际上它是1个矩形ProgressBar控件(命名为volume),但其左上角部分用1个和背景颜色(黑色)一致的Path(用钢笔工具手绘)覆盖,看到的是三角形。volume和Path组合在grid3中。

    volume控件属性设置(“公共属性”栏目中):

    Maximum:1             Minimum:0

    volume控件的Value属性(默认值改设为0.6,原来是0.5)采用数据绑定设置:在【属性】面板的“公共属性”栏中选Value属性—鼠标左键点击右侧的白色方块(高级选项),在弹出的菜单中选择“数据绑定”,这时出现“创建数据绑定”窗口,选择“元素属性”页面,左侧场景元素中选“me”控件,右侧属性中选Value,点“确定”键完成设置。me控件的音量将跟随volume控件的Value变化。

    喇叭图标由图形组合而成,最后组合在Grid控件(mute)中,构成静音/播音反复控制,如果处于静音喇叭图标上又多出红色“×”(组合在grid5中),程序如下。

 

  1. //音量控制  
  2.  
  3.      private void volume_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)  
  4.  
  5.      {  
  6.  
  7.          //获取ProgressBar控件对应的音量值  
  8.  
  9. this.me.Volume=e.GetPosition(this.volume).X/this.volume.ActualWidth;            
  10.  
  11.      }  
  12.  
  13.     //静音控制  
  14.  
  15.      private void mute_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)  
  16.  
  17.      {  
  18.  
  19.          this.me.IsMuted=!this.me.IsMuted;  
  20.  
  21.          if (this.me.IsMuted)  
  22.  
  23.               //如果是静音,显示红色×  
  24.  
  25.               this.grid5.Visibility=Visibility.Visible;  
  26.  
  27.          else  
  28.  
  29.               this.grid5.Visibility=Visibility.Collapsed;  
  30.  
  31.      }  
  32.  

4、进度条设置和预览窗口

    MediaElement控件本身有边下载边播放的功能,这里使用图图2-5中间的进度条控件ProgressBar(名为progressbar)的进度值显示视频下载进度,同时又在其中附加了1个矩形控件(名为vernier,红色)作为游标用于显示播放进度,这2个控件组合放置在Canvas中(名为canvas2),canvas2的大小和progressbar一致,这样方便游标vernier的位置设置。当点击进度条时视频就会选择从点击处对应的视频位置开始播放。另外有3个文本框分别显示下载的缓冲进度(textblock1)、播放器当前状态(textblock2)和视频播放时的时间进度(textblock3)。

    关于缓冲进度:当me控件的属性Source被赋值后,自动产生下载缓冲过程,下载缓冲时间属性BufferingTime默认值是00:00:05(5秒,在“媒体”属性栏目中),此值的大小会影响视频播放的平滑程度,当然和网络速度也有关,本实例中设置500ms:

    this.me.BufferingTime=TimeSpan.FromMilliseconds(500);

    但实际的缓冲值在0-1之间变化,乘以100后相当于百分比,1个100%应当对应1个下载缓冲时间,1个视频的下载可能要经过若干个这样的过程。而且当1个缓冲完成时自动产生BufferProgressChanged事件,缓冲的显示正是在此事件的程序中设计的。

    缓冲变化会使视频文件下载进度变化,而此变化也会产生DownloadProgressChanged事件,可以在其中编写程序显示下载进度属性DownloadProgress的变化值(0-1之间)。

    关于播放器状态,MedaiElement控件在视频下载和播放时有如下状态:

    Buffering、Closed、Opening、Paused、Playing 或 Stopped。默认值为 Closed,这些状态根据英文就能理解它的含义,不再解释。状态的显示也是在此BufferProgressChanged事件程序中设计的。

    图2-4下方有5个图形图标,代表5个视频,当点击时就会产生下载播放过程,下面以点击左边的图标“机场”为例,看如何编写程序的。

 

  1. //播放"机场"视频  
  2.  
  3.      private void image1_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)  
  4.  
  5.      {  
  6.  
  7. //定时器停止,定时器的作用后面介绍  
  8.  
  9.          timer.Stop();  
  10.  
  11. //下载进度值回0  
  12.  
  13.          this.progressbar.Value=0;  
  14.  
  15.          //获取当前浏览位置定位(含网页文件名称),如:http://localhost:2277/Default.html  
  16.  
  17.          uri=System.Windows.Browser.HtmlPage.Document.DocumentUri.ToString();  
  18.  
  19.          //LastIndexOf("/"):搜寻定位中右边最后1个"/"的位置,其左侧是不含网页文件的定位                //形成服务器视频文件的位置信息  
  20.  
  21.          videoname=uri.Substring(0,uri.LastIndexOf("/")+1)+"video/video1.wmv";  
  22.  
  23.          //设置视频播放控件的视频源  
  24.  
  25.          this.me.Source=new Uri(videoname,UriKind.RelativeOrAbsolute);  
  26.  
  27. //设置预览视频源,后面会介绍视频预览  
  28.  
  29.          thisthis.preview.Source=this.me.Source;  
  30.  
  31.          this.preview.Stop();  
  32.  
  33.          //设置视频文件打开后的事件  
  34.  
  35.          this.me.MediaOpened+=new RoutedEventHandler(meOpened);  
  36.  
  37.          //设置下载进度变化事件  
  38.  
  39.          this.me.DownloadProgressChanged+=new RoutedEventHandler(meDownload);  
  40.  
  41. //设置下载缓冲时间  
  42.  
  43.          this.me.BufferingTime=TimeSpan.FromMilliseconds(500);  
  44.  
  45.          //设置下载缓冲变化的事件  
  46.  
  47.      this.me.BufferingProgressChanged+=new RoutedEventHandler(me_BufferingProgressChanged);  
  48.  
  49.      }  
  50.  
  51. //下载进度显示  
  52.  
  53.      private void meDownload(object sender, System.Windows.RoutedEventArgs e)  
  54.  
  55.      {  
  56.  
  57.          //DownloadProgress是下载进度,变化范围0-1  
  58.  
  59.          thisthis.progressbar.Value=this.me.DownloadProgress*this.progressbar.Maximum;  
  60.  
  61.      }  
  62.  
  63.      //下载缓冲变化显示  
  64.  
  65.      double bp=0;  
  66.  
  67.      private void me_BufferingProgressChanged(object sender,RoutedEventArgs e){  
  68.  
  69.          //BufferingProgress:缓冲变化值0-1  
  70.  
  71.          bp=this.me.BufferingProgress*100;  
  72.  
  73.          this.textblock1.Text="下载缓冲进度:"+bp.ToString()+"%";  
  74.  
  75.           this.textblock2.Text="播放器当前状态:"+me.CurrentState.ToString();  
  76.  
  77.      }  
  78.  
  79. //文件打开后定时器启动  
  80.  
  81.      private void meOpened(object sender, System.Windows.RoutedEventArgs e)  
  82.  
  83.      {  
  84.  
  85.          timer.Start();  
  86.  
  87.      }  
  88.  
  89. //当点击进度条时,选择视频播放位置  
  90.  
  91.      private void progressbar_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)  
  92.  
  93.      {  
  94.  
  95.          this.me.Pause();  
  96.  
  97.          this.me.Position=TimeSpan.FromSeconds(currentlength);  
  98.  
  99.          this.me.Play();  
  100.  
  101.      }  
  102.  
  103.     在本机实际调试时,可能看不到缓冲变化和播放状态,但是如果放到服务器上调试就会很明显,本实例已经在网络服务器上调试验证。  
  104.  
  105.     以上的程序大多数代码在前面已经有了解释,还有视频预览preview和定时器timer没有涉及到。  
  106.  
  107.     Preview也是1个MediaElement控件(和边框矩形设计一起组合在canvas2的grid4中),当视频已经下载并播放时,如果鼠标悬停在进度条上立刻显示视频对应的时间,如果鼠标停止不动一段时间(比如2秒),会自动弹出视频预览窗口,看到的是鼠标悬停处对应的视频,此预览只反复播放悬停处的几帧视频图像。鼠标离开或变化位置自动停止,这点和目前网上看到的有的视频播放器的效果是一样的。  
  108.  
  109. 这里用到时间控制,由定时器来完成,程序如下:  
  110.  
  111. private DispatcherTimer timer=new  DispatcherTimer();  
  112.  
  113. //定义变量,用于视频源地址和文件位置信息变量  
  114.  
  115.      string uri,videoname;  
  116.  
  117.      public MainPage()  
  118.  
  119.      {  
  120.  
  121.          InitializeComponent();  
  122.  
  123. //Esc键提示关闭  
  124.  
  125.          this.Esctext.Visibility=Visibility.Collapsed;  
  126.  
  127. //进度条当前位置显示文本框关闭  
  128.  
  129.          this.cp.Visibility=Visibility.Collapsed;  
  130.  
  131. //预览窗口关闭  
  132.  
  133.          this.grid4.Visibility=Visibility.Collapsed;  
  134.  
  135.          timer.Interval=TimeSpan.FromMilliseconds(500);  
  136.  
  137.          timer.Tick+=new EventHandler(timerarrive);  
  138.  
  139. //设置视频播放进度游标初始位置  
  140.  
  141.          Canvas.SetLeft(this.vernier,0);  
  142.  
  143.          Canvas.SetTop(this.vernier,0);             
  144.  
  145.      }  
  146.  
  147.      //定时器定时访问程序  
  148.  
  149. //视频时间总长度和视频进度条当前值变量  
  150.  
  151.      double melength=0,currentvalue;  
  152.  
  153. //记忆鼠标悬停位置  
  154.  
  155.      double movevalue=0;  
  156.  
  157. //悬停不动时间计数和预览时间计数  
  158.  
  159.      double times=0,previewtimes=0;  
  160.  
  161. //鼠标移动  
  162.  
  163.      bool move=false;  
  164.  
  165.      private void timerarrive(object sender,EventArgs e){  
  166.  
  167. //获取视频时间总长度  
  168.  
  169.          memelength=me.NaturalDuration.TimeSpan.TotalSeconds;  
  170.  
  171.          //视频进度条当前值=视频进度条最大值*视频当前位置时间/视频时间总长度  
  172.  
  173.          currentvalue=this.progressbar.ActualWidth*me.Position.TotalSeconds/melength;  
  174.  
  175. //设置视频进度游标位置  
  176.  
  177.          Canvas.SetLeft(this.vernier,currentvalue);  
  178.  
  179. //获取视频当前位置时间小时值、分值、秒值  
  180.  
  181.           int h=me.Position.Hours;  
  182.  
  183.          int m=me.Position.Minutes;  
  184.  
  185.          int s=me.Position.Seconds;  
  186.  
  187. //下面使用了C#的条件运算符<条件>?<满足条件时>:<不满足条件时> 
  188.  
  189.          this.textblock3.Text="播放时间进度:"+(h<10? "0"+h.ToString():h.ToString())+":"  
  190.  
  191.                       +(m<10? "0"+m.ToString():m.ToString())+":"  
  192.  
  193.                       +(s<10? "0"+s.ToString():s.ToString());  
  194.  
  195.          //预览视频处理  
  196.  
  197.          if (times<4)  
  198.  
  199. //计数控制+1(位置不变的次数)  
  200.  
  201.              times++;  
  202.  
  203.               if (times==1){  
  204.  
  205.                   //取当前鼠标X位置  
  206.  
  207.                   movevalue=progressbarX;  
  208.  
  209. }  
  210.  
  211. //如果鼠标滑动在进度条且X坐标没有变化,且计数达4次  
  212.  
  213.               if (move && movevalue==progressbarX){  
  214.  
  215.                    if (times==4){  
  216.  
  217. //开启预览窗口  
  218.  
  219.                        this.grid4.Visibility=Visibility.Visible;  
  220.  
  221.                        //如果预览窗口当前处于播放状态  
  222.  
  223.                        if (this.preview.CurrentState==MediaElementState.Playing){  
  224.  
  225. //预览时间控制计数  
  226.  
  227.                             previewtimes++;  
  228.  
  229. //达到预览时间  
  230.  
  231.                             if (previewtimes==4)  
  232.  
  233. //暂停预览  
  234.  
  235.                                  this.preview.Pause();                      
  236.  
  237.                        }else{  
  238.  
  239. //设置预览视频位置  
  240.  
  241.                         this.preview.Position=current;  
  242.  
  243. //启动视频预览,且设置预览时间控制计数回0  
  244.  
  245.                        this.preview.Play();  
  246.  
  247.                        previewtimes=0;  
  248.  
  249. }  
  250.  
  251.                    }  
  252.  
  253.          }else{  
  254.  
  255.               //关闭预览窗口,同时位置不变的次数计数回0  
  256.  
  257.               this.grid4.Visibility=Visibility.Collapsed;  
  258.  
  259.               times=0;  
  260.  
  261. }           
  262.  
  263.          }  
  264.  
  265.     定时访问程序中用到的一些变量,如progressbarX、move等,和下列程序有关:  
  266.  
  267. //定义变量,用于当前位置时间值和鼠标X坐标  
  268.  
  269.      double currentlength,progressbarX;  
  270.  
  271. //进度条鼠标悬停处的时间  
  272.  
  273.      TimeSpan current;  
  274.  
  275. //鼠标悬停在进度条上方,进度条当前位置时间显示  
  276.  
  277.      private void progressbar_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)  
  278.  
  279.      {  
  280.  
  281.           //事件引发者是ProgressBar控件  
  282.  
  283.          ProgressBar pb=sender as ProgressBar;  
  284.  
  285. //视频时间总长度  
  286.  
  287.          memelength=me.NaturalDuration.TimeSpan.TotalSeconds;  
  288.  
  289.          //进度条当前位置时间值      currentlength=melength*e.GetPosition(this.progressbar).X/this.progressbar.ActualWidth;  
  290.  
  291.          int h=(int)currentlength/3600;  
  292.  
  293.          int m=(int)((currentlength600)/60);  
  294.  
  295.          int s=(int)((currentlength600)`);  
  296.  
  297. //设置视频进度游标位置  
  298.  
  299.          Canvas.SetLeft(this.cp,e.GetPosition(this.progressbar).X-30);  
  300.  
  301.           Canvas.SetLeft(this.grid4,e.GetPosition(this.progressbar).X-54);  
  302.  
  303.           //当前位置显示使用Callout(cp)控件  
  304.  
  305.          this.cp.Visibility=Visibility.Visible;  
  306.  
  307.          this.cp.Content=(h<10? "0"+h.ToString():h.ToString())+":"  
  308.  
  309.                          +(m<10? "0"+m.ToString():m.ToString())+":"  
  310.  
  311.                         +(s<10? "0"+s.ToString():s.ToString());  
  312.  
  313.          current=TimeSpan.Parse(this.cp.Content.ToString());  
  314.  
  315.          move=true;  
  316.  
  317.          progressbarX=e.GetPosition(this.progressbar).X;             
  318.  
  319.      }  
  320.  
  321.      //鼠标离开进度条  
  322.  
  323.      private void progressbar_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)  
  324.  
  325.      {  
  326.  
  327.           //关闭预览,关闭进度条当前位置时间显示  
  328.  
  329.          this.grid4.Visibility=Visibility.Collapsed;  
  330.  
  331.          this.cp.Visibility=Visibility.Collapsed;  
  332.  
  333. //停止鼠标移动  
  334.  
  335.          move=false;  
  336.  
  337. //鼠标悬停不动时间计数置0,鼠标悬停位置回0  
  338.  
  339.          times=0;  
  340.  
  341.          movevalue=0;  
  342.  
  343. //预览播放停止,预览计数回0  
  344.  
  345.          this.preview.Stop();  
  346.  
  347.          previewtimes=0;  
  348.  
  349. }  
  350.  
  351. 5、播放控制  
  352.  
  353.     对视频的“暂停”、“播放”、“停止”、“重播”等控制图标采用了故事板动画,当鼠标悬停在这些图标上时颜色发生变化(本例变为绿色),程序比较简单:  
  354.  
  355. //暂停按钮控制  
  356.  
  357.      private void pause_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)  
  358.  
  359.      {  
  360.  
  361.          this.Storyboard1.Begin();  
  362.  
  363.      }  
  364.  
  365.      private void pause_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)  
  366.  
  367.      {  
  368.  
  369.          this.Storyboard1.Stop();  
  370.  
  371.      }  
  372.  
  373.      private void pause_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)  
  374.  
  375.      {  
  376.  
  377.          this.me.Pause();  
  378.  
  379.      }  
  380.  
  381.      //播放按钮控制  
  382.  
  383.      private void play_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)  
  384.  
  385.      {  
  386.  
  387.          this.Storyboard2.Begin();  
  388.  
  389.      }  
  390.  
  391.      private void play_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)  
  392.  
  393.      {  
  394.  
  395.          this.Storyboard2.Stop();  
  396.  
  397.      }  
  398.  
  399.      private void play_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)  
  400.  
  401.      {  
  402.  
  403.          this.me.Play();  
  404.  
  405.      }  
  406.  
  407.      //停止按钮控制  
  408.  
  409.      private void stop_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)  
  410.  
  411.      {  
  412.  
  413.          this.Storyboard3.Begin();  
  414.  
  415.      }  
  416.  
  417.      private void stop_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)  
  418.  
  419.      {  
  420.  
  421.          this.Storyboard3.Stop();  
  422.  
  423.      }  
  424.  
  425.      private void stop_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)  
  426.  
  427.      {  
  428.  
  429.          this.me.Stop();  
  430.  
  431.      }  
  432.  
  433.      //重播按钮控制  
  434.  
  435.      private void replay_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)  
  436.  
  437.      {  
  438.  
  439.          this.Storyboard4.Begin();  
  440.  
  441.      }  
  442.  
  443.      private void replay_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)  
  444.  
  445.      {  
  446.  
  447.          this.Storyboard4.Stop();  
  448.  
  449.      }  
  450.  
  451.      private void replay_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)  
  452.  
  453.      {  
  454.  
  455.          this.me.Stop();  
  456.  
  457.          this.me.Play();  
  458.  
  459. }  
  460.  
  461. 6、全屏播放控制  
  462.  
  463.     Silverlight本身有全屏播放的控制语句:  
  464.  
  465. Application.Current.Host.Content.IsFullScreen=!Application.Current.Host.Content.IsFullScreen;  
  466.  
  467. 但是,此语句控制的是当前显示界面的全屏显示,而我们只希望视频部分全屏播放,本实例中编程先将视频放到浏览器的“全屏”(浏览器菜单和工具条保留)大小(程序设计指定按Esc键恢复原始大小),然后再使用上述语句放大到全屏,此语句默认并提示按Esc取消全屏,这样当程序运行时第一次按Esc键实际恢复到浏览器“全屏”,第二次再按Esc键恢复到原始大小,程序如下。  
  468.  
  469. //全屏控制  
  470.  
  471.      private void fullscreen_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)  
  472.  
  473.      {  
  474.  
  475.          this.Storyboard5.Begin();  
  476.  
  477.      }  
  478.  
  479.      private void fullscreen_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)  
  480.  
  481.      {  
  482.  
  483.          this.Storyboard5.Stop();  
  484.  
  485.      }  
  486.  
  487.      //定义变量,记忆初始值  
  488.  
  489.      double canvas1W,canvas1H,meW,meH,meLeft,meTop;  
  490.  
  491.      private void fullscreen_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)  
  492.  
  493.      {  
  494.  
  495.          //视频播放时才能使用全屏操作  
  496.  
  497.          if (this.me.CurrentState==MediaElementState.Playing){  
  498.  
  499. //记忆Canvas(me控件的容器)的原始大小  
  500.  
  501.          canvas1W=this.canvas1.ActualWidth;  
  502.  
  503.          canvas1H=this.canvas1.ActualHeight;  
  504.  
  505.          //记忆me控件的原始大小,以及me控件的原始位置  
  506.  
  507. meW=this.me.ActualWidth;  
  508.  
  509.          meH=this.me.ActualHeight;  
  510.  
  511.          meLeft=Canvas.GetLeft(me);  
  512.  
  513.          meTop=Canvas.GetTop(me);  
  514.  
  515.           //布局控件放大到当前应用程序(在浏览器中)界面大小  
  516.  
  517.          this.canvas1.Width=Application.Current.Host.Content.ActualWidth;  
  518.  
  519.          this.canvas1.Height=Application.Current.Host.Content.ActualHeight;  
  520.  
  521. //设置me控件层次到上层(20是界面元素个数最大值,实际没有这么多)  
  522.  
  523.           Canvas.SetZIndex(me,20);  
  524.  
  525.          //视频控件也放大到当前应用程序界面大小  
  526.  
  527.          thisthis.me.Width=this.canvas1.Width;  
  528.  
  529.          thisthis.me.Height=this.canvas1.Height;  
  530.  
  531. //视频控件位置设置  
  532.  
  533.          Canvas.SetLeft(me,0);  
  534.  
  535.          Canvas.SetTop(me,0);  
  536.  
  537. //使用按Esc键提示,以及按Esc键提示框位置,并将提示框放置最上层  
  538.  
  539.          this.Esctext.Visibility=Visibility.Visible;  
  540.  
  541.          Canvas.SetLeft(Esctext,0);  
  542.  
  543.          Canvas.SetTop(Esctext,0);  
  544.  
  545.          Canvas.SetZIndex(Esctext,21);  
  546.  
  547.          //设置按Esc键事件(自定义)  
  548.  
  549.          Application.Current.RootVisual.KeyDown += new KeyEventHandler(ESC_Down);  
  550.  
  551.          //使用Silverlight的全屏控制Application.Current.Host.Content.IsFullScreen=!Application.Current.Host.Content.IsFullScreen;  
  552.  
  553.           }  
  554.  
  555.      }  
  556.  
  557.      private void ESC_Down(object sender, KeyEventArgs e)  
  558.  
  559.      {  
  560.  
  561.            //如果按下Esc键  
  562.  
  563.          if (e.Key.ToString()=="Escape"){  
  564.  
  565. //Esc键提示框关闭,恢复布局原始大小  
  566.  
  567.               this.Esctext.Visibility=Visibility.Collapsed;                 
  568.  
  569.              this.canvas1.Width=canvas1W;  
  570.  
  571.              this.canvas1.Height=canvas1H;  
  572.  
  573. //恢复me控件原始大小,置于底层,并恢复原始位置  
  574.  
  575.               this.me.Width=meW;  
  576.  
  577.               this.me.Height=meH;  
  578.  
  579.               Canvas.SetZIndex(me,0);  
  580.  
  581.              Canvas.SetLeft(me,meLeft);  
  582.  
  583.               Canvas.SetTop(me,meTop);  
  584.  
  585.          }