Silverlight具有打印功能,可以选择性地打印页面上的对象,下面给出的实例项目展示了Silverlight的“基本打印功能”(在项目的Page1.xaml中),MainPage.xaml的页面安排了1个链接可以跳转到Page1.xaml。下面分别介绍。

1. 基本打印功能界面

4-19是基本打印功能的界面。

4-19给出了Page1.xaml中打印页面图片和文本的2个设计,图片Image的控件名为p_w_picpath1,其中的按钮控件名为BtprintImage,右侧文本框控件TextBlock的名为textblock1,其中的按钮控件名为BtprintText。它们都分别组合在Grid布局控件中。设计语句不复杂。

Silverlight的打印依靠PrintDocument类,它提供了打印对话框、打印操作和打印完成处理等功能。下面是初始化语句:

首先要为使用PrintDocument类添加命名空间引用:

using System.Windows.Printing;

图4-19

 

 
  
  1. 程序开始的初始化:  
  2. //定义图片和文本打印变量  
  3.     PrintDocument printImage,printText;  
  4.     public Page1()  
  5.         {  
  6.             InitializeComponent();  
  7.             //图片打印对象  
  8.             printImage = new PrintDocument();  
  9.             //图片打印事件处理  
  10.             printImage.PrintPage += new  
  11.  EventHandler<PrintPageEventArgs>(printImage_PrintPage);  
  12. //文本打印对象  
  13.             printText = new PrintDocument();  
  14.             //文本打印事件处理  
  15.             printText.PrintPage += new   
  16. EventHandler<PrintPageEventArgs>(printText_PrintPage);  
  17. }  
  18. //点击图片打印按钮  
  19. private void BTprintImage_Click(object sender,   
  20. System.Windows.RoutedEventArgs e)  
  21.         {  
  22.              //启动打印图片,出现打印对话框  
  23.             printImage.Print("iamge1");  
  24.         }  
  25.      //确认打印后开始打印  
  26.      void printImage_PrintPage(object sender, PrintPageEventArgs e)  
  27.        {  
  28.             //确认打印,打印对象  
  29.             e.PageVisual = p_w_picpath1;            
  30.         }  
  31. 当启动打印时会出现和Windows下的打印对话框,如图4-20。  

 

图4-20

    在图4-20中可以选择打印机,确定是否打印。如果打印就会开始打印。

文本框打印复杂一点,本例中首先将文本框textblock1的文本添加到Stackpanel布局控件中(也可以是其它容器控件,如Grid),然后再启动打印,后面的过程和打印图片一样。

 

 
  
  1. /定义布局控件变量  
  2. StackPanel printarea;  
  3.      private void BTprintText_Click(object sender,   
  4. System.Windows.RoutedEventArgs e)  
  5.         {  
  6.             //打印文本的的字符长度,压缩尾部空格  
  7. int length=this.textblock1.Text.TrimEnd().Length;  
  8. //打印宽度设置  
  9.               int w=18;  
  10.              //布局对象,StackPanel默认纵向排列添加的对象  
  11. printarea=new StackPanel();  
  12. //获取文本,直到文本尾  
  13.               for (int i=0;i<=length;ii=i+w)  
  14.                 {  
  15.                     //如果文本剩余长度不小于设定宽度  
  16. if (this.textblock1.Text.TrimEnd().Substring(i).Length>=w){  
  17.                    //布局控件添加文本对象,按设置宽度截取文本,设置字体字号      
  18. printarea.Children.Add(new   
  19. TextBlock(){Text=this.textblock1.Text.Trim().  
  20. Substring(i,w),   
  21.                        FontFamily=  
  22. new System.Windows.Media.FontFamily("Arial"),FontSize=12});   
  23.                     }else {  
  24.                      //否则一直截取到文本尾  
  25. printarea.Children.Add(new  
  26. TextBlock(){Text=  
  27. this.textblock1.Text.TrimEnd().Substring(i),   
  28.                        FontFamily=  
  29. new System.Windows.Media.FontFamily("Arial"),FontSize=12});   
  30.                     }  
  31.                 }  
  32. //启动打印    
  33.              printText.Print("文本打印");         
  34.         }  
  35.        //确认打印后开始打印  
  36.       void printText_PrintPage(object sender, PrintPageEventArgs e)  
  37.         {  
  38.             e.PageVisual =printarea;  
  39.         }  

 

2. 具有“打印预览和排版”效果的打印设计

4-21 具有打印预览排版效果的设计界面

 

4-22 打印预览窗口

预览窗口有1个打印区,大小类似A4版面。其中有如下控件:

字体选择使用组合框ComboBox控件(名为combobox1),用于选择字体,本例只采用了部分字体。字号选择也采用ComboBox控件(名为combobox2)用于选择字号,本例只采用了部分字号,最大到243个按钮“预览”(名为view)、“打印”(名为print)和“关闭”(名为exit)。打印区实际上是1Canvas布局控件(名为canvasprint),其Top位于上述控件的下边缘。

    打印区中有1个打印对象(有背景色),是Grid控件(名为printarea),打印对象位于canvasprint中,使用Canvas控件方便打印对象的位置设置。图2-55中已经添加了富文本控件RichTextBox(如果打印图片添加的是Image控件),周边有4个由Rectangle控件组成的红色移动标,从上、左、下、右依次分别命名为rec1rec2rec3rec4。其中拖动rec1可以移动打印对象在打印区的位置;拖动rec2可以向左增大或缩小打印对象的宽度;拖动rec3可以增加或缩小打印对象的高度;拖动rec4可以向右增大或缩小打印对象的宽度。这4个移动标可以实现打印对象在打印区的自由布局。另外,对于文本来说,由于使用RichTextBox,当移动标移动时RichTextBox的宽度、高度也跟随变化,其中的文本自动重新排列。移动图片的过程比文本要简单一些。

    打印时,4个移动标、打印对象的背景和RichTextBox的边框也会被打印出来,所以安排了相关设计,打印时隐藏这些部分,打印后再显示。进入预览窗口后首先要点击“预览”按钮才能看到预览效果,当改变字体、字号、取消打印时都需要重新点击“预览”按钮,起到刷新作用。

下面是程序。

MainPage.xaml.cs开始添加了命名空间引用:

using System.Windows.Printing;//for PrintDocument

using System.Windows.Media.Imaging;//for BitmapImage

程序初始化部分:

 

 
  
  1. //设置打印变量  
  2. PrintDocument printer;  
  3. //字符串变量prn用于区分图片打印和文本打印  
  4.     string prn;  
  5. //打印对象控件尺寸和坐标变量设置,分别对应宽、高、左边距、上边距  
  6. double w,h,left,top;  
  7. double x,y; //记录打印对象变化坐标,动态变化值  
  8.      //打印对象Grid的背景色,橘红色  
  9.     SolidColorBrush scb=new SolidColorBrush(Colors.Orange);      
  10.     string ztselected; //记录选择的字体       
  11.     int zhselected; //记录选择的字号  
  12.      //定义富文本控件,用于动态获取打印文本的字符串  
  13.     RichTextBox newnewtb=new RichTextBox();  
  14. WriteableBitmap wb; // WriteableBitmap类用于截取视频“快照”  
  15. public MainPage()  
  16.         {  
  17.             InitializeComponent();               
  18.             this.ChildView.HasCloseButton=false; //不需要子窗口的关闭按钮  
  19.             //子窗口标题栏设置,使用定义StackPanel控件设置布局  
  20.             StackPanel titlepanel=new StackPanel();  
  21.               //StackPanel控件水平排列对象  
  22.             titlepanel.Orientation=Orientation.Horizontal;  
  23.               //设置鼠标悬浮在标题栏时的形状  
  24.             titlepanel.Cursor=Cursors.Hand;  
  25.               //定义1个图标,用于标题栏  
  26.             Image im=new Image();  
  27.             im.Width=20;  
  28.             im.Height=20;  
  29.             im.Source=new BitmapImage(new Uri("sucai/icon16.png",   
  30. UriKind.Relative));                
  31.             titlepanel.Children.Add(im); //标题栏首先添加图标                
  32.             TextBlock text=new TextBlock();//标题栏添加文本框,设置标题提示  
  33.             text.Text="  打印预览……";  
  34.             text.Width=this.ChildView.Width;  
  35.             text.FontSize=12;  
  36.             titlepanel.Children.Add(text);                
  37.             this.ChildView.Title=titlepanel; //子窗口标题栏设置  
  38.             //打印预览子窗口设置,默认字体Arial,默认字号12  
  39.             // combobox1的第1个选择项(序号0)是Arial  
  40.             this.combobox1.SelectedIndex=0;  
  41.             // combobox2的第2个选择项(序号1)是12  
  42.             this.combobox2.SelectedIndex=1;  
  43.             //打印对象背景设置,即Grid控件的背景  
  44.             this.printarea.Background=scb;              
  45.             w=this.printarea.Width; //记录打印对象的初始参数  
  46.             h=this.printarea.Height;  
  47.              //7是移动标Rectangle边长的一半,保证移动标中心和打印对象的边重合  
  48.             left=Canvas.GetLeft(this.printarea)-7;  
  49.             top=Canvas.GetTop(this.printarea)-7;  
  50.              //设置移动标的位置,分布在打印对象4个边的中间位置  
  51.             SetRecPosition();             
  52.             printer = new PrintDocument();//设置打印对象  
  53.              //设置打印开始事件  
  54.             printer.PrintPage +=   
  55. new EventHandler<PrintPageEventArgs>(printer_PrintPage);  
  56.              //设置打印结束事件  
  57.             printer.EndPrint+=   
  58. new EventHandler<EndPrintEventArgs>(printer_EndPrintPage);  
  59. }  
  60. //设置移动标位置  
  61. private void SetRecPosition(){  
  62.             Canvas.SetLeft(rec1,left+w/2);  
  63.             Canvas.SetTop(rec1,top);  
  64.             Canvas.SetLeft(rec2,left);  
  65.             Canvas.SetTop(rec2,top+h/2);  
  66.             Canvas.SetLeft(rec3,left+w/2);  
  67.             Canvas.SetTop(rec3,top+h);  
  68.             Canvas.SetLeft(rec4,left+w);  
  69.             Canvas.SetTop(rec4,top+h/2);  
  70.     }  
  71. //点击图片打印预览按钮  
  72. private void BTprintImage_Click(object sender,  
  73. System.Windows.RoutedEventArgs e)  
  74.         {              
  75. prn="p_w_picpath";//记录打印对象  
  76. //子窗口弹出(默认隐藏)  
  77.            this.ChildView.Visibility=Visibility.Visible;  
  78.             //打印对象清空(请Grid中的子对象)  
  79.            this.printarea.Children.Clear();  
  80.         }  
  81.         //点击文本打印预览  
  82.      private void BTprintText_Click(object sender,   
  83. System.Windows.RoutedEventArgs e)  
  84.         {  
  85.                  prn="text";              
  86.             this.ChildView.Visibility=Visibility.Visible;  
  87.             this.printarea.Children.Clear();  
  88.         }  
  89.         //点击截取视频图片打印预览  
  90.      private void BTprintVideo_Click(object sender,   
  91. System.Windows.RoutedEventArgs e)  
  92.         {  
  93.             //截取视频“快照”  
  94. wb = new WriteableBitmap(me, null);//快照截图  
  95.             prn="video";  
  96.             this.ChildView.Visibility=Visibility.Visible;  
  97.             this.printarea.Children.Clear();  
  98.         }  
  99.         //预览子窗口程序,预览判断和预览  
  100.        string subs;  
  101.      private void view_Click(object sender, System.Windows.RoutedEventArgs e)  
  102.         {  
  103.                  this.printarea.Children.Clear();  
  104.               //恢复移动标显示  
  105.             this.rec1.Visibility=Visibility.Visible;  
  106.             this.rec2.Visibility=Visibility.Visible;  
  107.             this.rec3.Visibility=Visibility.Visible;  
  108.             this.rec4.Visibility=Visibility.Visible;  
  109.               //富文本框滚动条设置  
  110.             newtb.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;  
  111.               //富文本框边框宽度设置  
  112.             newnewtb.BorderThickness=new Thickness(1,1,1,1);  
  113.               //打印对象背景颜色设置  
  114.             this.printarea.Background=scb;        
  115.             switch (prn){  
  116.                 case "p_w_picpath":  
  117.                     //打印图片,添加Image控件,获取图片源  
  118.                   this.printarea.Children.Add(new Image(){Source=new BitmapImage(new Uri("sucai/im2.jpg", UriKind.Relative)),  
  119.                      StretchStretch=Stretch.Uniform});  
  120.                   break;  
  121.                 case "video":  
  122.                      //打印视频截图,添加Image控件,获取图片源  
  123.                   this.printarea.Children.Add(new Image(){Source=wb,  
  124.                      StretchStretch=Stretch.Uniform});  
  125.                   break;  
  126.                 case "text":  
  127. //获取文本字号    
  128. zhselected=  
  129. Convert.ToInt32(this.combobox2.SelectionBoxItem.ToString());  
  130.                   //获取文本字体字体  
  131.                   ztselected=this.combobox1.SelectionBoxItem.ToString();                       
  132.                   newtb.Blocks.Clear();//富文本内部清空  
  133.                   //富文本尺寸同打印对象(Grid)  
  134.                    newtb.Width=this.printarea.Width;  
  135.                    newtb.Height=this.printarea.Height;                       
  136.                    Run run1 = new Run();//定义富文本框中段落的子元素  
  137.                    run1.FontSize=zhselected;  
  138.                    run1.FontFamily=  
  139. new System.Windows.Media.FontFamily(ztselected);  
  140.                    run1.Text=this.textblock1.Text;  
  141.                    //定义富文本框的段落,段落由元素组成  
  142.                    Paragraph paragraph = new Paragraph();  
  143.                    //段落添加子元素  
  144.                    paragraph.Inlines.Add(run1);  
  145.                    //Blocks是富文本框的内容属性,是段落Paragraph的集合  
  146.                    newtb.Blocks.Add(paragraph);  
  147.                    //富文本框进入打印对象  
  148.                    this.printarea.Children.Add(newtb);   
  149.                    break;  
  150.             }  
  151.         }  
  152.     //启动打印  
  153. private void print_Click(object sender, System.Windows.RoutedEventArgs e)  
  154.         {  
  155.         //显示打印选择对话框,选择打印机,确认打印,隐藏移动标、边框、取消背景颜色  
  156.             this.rec1.Visibility=Visibility.Collapsed;  
  157.             this.rec2.Visibility=Visibility.Collapsed;  
  158.             this.rec3.Visibility=Visibility.Collapsed;  
  159.             this.rec4.Visibility=Visibility.Collapsed;  
  160.             newtb.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;  
  161.             newnewtb.BorderThickness=new Thickness(0,0,0,0);  
  162.             this.printarea.Background=null;  
  163.             //启动打印,出现打印对话框,选择打印机,确认是否打印  
  164.             printer.Print("打印……");  
  165.         }  
  166.     //确认打印后开始打印  
  167.     void printer_PrintPage(object sender, PrintPageEventArgs e)  
  168.         {  
  169.             e.PageVisual =canvasprint;  
  170.         }  
  171.     //结束打印(送出打印最后1页信息)  
  172.     void printer_EndPrintPage(object sender, EndPrintEventArgs e)  
  173.         {  
  174.              //恢复显示  
  175. this.rec1.Visibility=Visibility.Visible;  
  176.             this.rec2.Visibility=Visibility.Visible;  
  177.             this.rec3.Visibility=Visibility.Visible;  
  178.             this.rec4.Visibility=Visibility.Visible;  
  179.             newtb.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;  
  180.             newnewtb.BorderThickness=new Thickness(1,1,1,1);  
  181.             this.printarea.Background=scb;  
  182.         }  
  183.     //退出预览窗口  
  184.      private void exit_Click(object sender, System.Windows.RoutedEventArgs e)  
  185.         {  
  186.             this.ChildView.Visibility=Visibility.Collapsed;  
  187.         }  
  188.       //链接到Page1  
  189.      private void tb1_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)  
  190.         {  
  191.             this.Content=new Page1();  
  192.         }  
  193.      //移动标程序设计,记忆鼠标移动时的位置  
  194. Point curpos;  
  195. bool mousemoving=false; //是否拖动标志设置    
  196.     //鼠标选中rec1  
  197.      private void rec1_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)  
  198.         {                 
  199. curpos=e.GetPosition(null); //获取鼠标当前坐标  
  200. mousemoving=true; //设置标志,允许拖动  
  201. this.rec1.CaptureMouse();//鼠标捕获允许  
  202.         }  
  203.       //移动标rec1移动,在打印区移动打印对象位置  
  204.      private void rec1_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)  
  205.         {  
  206.             if (mousemoving){  
  207.              //计算鼠标X方向增加值  
  208.             double addX=e.GetPosition(null).X-curpos.X;  
  209. //计算鼠标Y方向增加值  
  210.             double addY=e.GetPosition(null).Y-curpos.Y;  
  211. //设置打印对象新位置坐标  
  212.             Canvas.SetLeft(printarea,addX+Canvas.GetLeft(printarea));  
  213.             Canvas.SetTop(printarea,addY+Canvas.GetTop(printarea));  
  214.             //计算边距,重新设置移动标的位置,保证移动标一直处于打印对象周边中央  
  215.             left=Canvas.GetLeft(this.printarea)-7;  
  216.             top=Canvas.GetTop(this.printarea)-7;  
  217.             SetRecPosition();  
  218.             curpos=e.GetPosition(null);   
  219.          }  
  220.         }  
  221.      //移动标rec1停止  
  222.      private void rec1_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)  
  223.         {                 
  224. mousemoving=false; //拖动禁止         
  225. this.rec1.ReleaseMouseCapture();//停止鼠标捕获  
  226.         }  
  227.     //鼠标选中rec2  
  228.     private void rec2_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)  
  229.         {  
  230.             curpos=e.GetPosition(null);  
  231.             y=Canvas.GetTop(printarea);  
  232.             top=y-7;  
  233.             mousemoving=true;  
  234.             this.rec2.CaptureMouse();  
  235.     }  
  236.      //移动标rec2移动改变打印区宽度  
  237. private void rec2_MouseMove(object sender,   
  238. System.Windows.Input.MouseEventArgs e)  
  239.         {  
  240.             if (mousemoving){  
  241.                  //计算鼠标X方向增加值  
  242.                 double addX=e.GetPosition(null).X-curpos.X;  
  243. //设置打印对象新位置坐标  
  244.                 Canvas.SetLeft(printarea,addX+Canvas.GetLeft(printarea));                     
  245.                 Canvas.SetTop(printarea,y); //y上边距不变化  
  246.                 //打印对象宽度变化  
  247.                 thisthis.printarea.Width=this.printarea.Width-addX;  
  248.                 this.printarea.Background=scb;  
  249.                 left=Canvas.GetLeft(this.printarea)-7;                
  250.                 w=this.printarea.Width;  
  251.                 SetRecPosition();                 
  252. newtb.Width=w; //富文本框宽度变化  
  253.                 curpos=e.GetPosition(null);   
  254.             }  
  255.         }  
  256.      //移动标rec2移动停止  
  257.     private void rec2_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)  
  258.         {  
  259.             mousemoving=false;        
  260.             this.rec2.ReleaseMouseCapture();  
  261.         }  
  262.      //鼠标选中rec4  
  263.     private void rec4_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)  
  264.         {  
  265.             curpos=e.GetPosition(null);  
  266.             y=Canvas.GetTop(printarea);  
  267.             x=Canvas.GetLeft(this.printarea);  
  268.             mousemoving=true;  
  269.             this.rec4.CaptureMouse();  
  270.         }  
  271.      //移动标rec4移动改变打印区宽度  
  272. private void rec4_MouseMove(object sender,   
  273. System.Windows.Input.MouseEventArgs e)  
  274.         {  
  275.             if (mousemoving){  
  276.                 double addX=e.GetPosition(null).X-curpos.X;  
  277.                 Canvas.SetLeft(printarea,x);//对象新位置坐标  
  278.                 Canvas.SetTop(printarea,y);  
  279.                 thisthis.printarea.Width=this.printarea.Width+addX;  
  280.                 this.printarea.Background=scb;  
  281.                 left=x-7;  
  282.                 top=y-7;  
  283.                 w=this.printarea.Width;  
  284.                 SetRecPosition();  
  285.                 newtb.Width=w;  
  286.                 curpos=e.GetPosition(null);   
  287.             }  
  288.         }  
  289.     //rec4停止拖动  
  290. private void rec4_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)  
  291.         {  
  292.             mousemoving=false;        
  293.             this.rec4.ReleaseMouseCapture();  
  294.         }  
  295.      //鼠标选中rec3  
  296.     private void rec3_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)  
  297.         {  
  298.             curpos=e.GetPosition(null);  
  299.             x=Canvas.GetLeft(printarea);  
  300.             y=Canvas.GetTop(printarea);  
  301.             top=y-7;  
  302.             w=this.printarea.Width;  
  303.             mousemoving=true;//允许拖动  
  304.             this.rec3.CaptureMouse();//鼠标捕获允许  
  305.         }  
  306.      //移动标rec3移动改变打印区高度  
  307.      private void rec3_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)  
  308.         {  
  309.             if (mousemoving){  
  310.                 double addY=e.GetPosition(null).Y-curpos.Y;                    
  311.                 Canvas.SetLeft(printarea,x); //位置没有变化  
  312.                 Canvas.SetTop(printarea,y);                     
  313.                 thisthis.printarea.Height=this.printarea.Height+addY; //高度变化  
  314.                 this.printarea.Background=scb;  
  315.                 left=Canvas.GetLeft(this.printarea)-7;                
  316.                 h=this.printarea.Height;  
  317.                 SetRecPosition();                     
  318.                 newtb.Height=h; //富文本框高度变化  
  319.                 curpos=e.GetPosition(null);   
  320.             }  
  321.         }  
  322.     //左下角移动标rec3移动停止  
  323.     private void rec3_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)  
  324.         {  
  325.             mousemoving=false;        
  326.             this.rec3.ReleaseMouseCapture();  
  327.         }  
  328. //视频播放结束再启动播放  
  329.     private void me_MediaEnded(object sender, System.Windows.RoutedEventArgs e)  
  330.         {  
  331.             this.me.Stop();  
  332.             this.me.Play();  
  333.         }  

 

具有一定排版效果的打印设计界面如图4-21所示,在MainPage.xaml中,和图4-19相比,仅仅是图片和文本“打印”按钮的标题改为“进入预览”,控件的名称同上,文本的长度长一点,多了1个视频截图打印,视频控件MediaElement的名为me,其中的按钮名为BTprintVideo。这里设计了预览窗口,是1ChildWindow(名为ChildView)子窗口,预览窗口的界面如图4-22所示。