驻马店网站建设价格,网站推广营销怎么做,公司的网站备案,做电商设计有什么好的网站推荐转自#xff1a;http://blog.sina.com.cn/s/blog_624dc0120100ld6m.html 最近在做一个WPF方面的项目#xff0c;在打印功能实现上费了很大劲。因为我原来是在做Winform方面的项目#xff0c;接受WPF时感觉还很相似#xff0c;可仔细往里做下去却发现两者外看相似#xff0… 转自http://blog.sina.com.cn/s/blog_624dc0120100ld6m.html 最近在做一个WPF方面的项目在打印功能实现上费了很大劲。因为我原来是在做Winform方面的项目接受WPF时感觉还很相似可仔细往里做下去却发现两者外看相似实则差异很大打印就是其中很大的差距。Winform有对应的对话框围绕打印核心类PrintDocument进行操作而WPF里则是在PrintDialog里进行扩展。WPF简单的打印很简单几行代码就够可要实现较大功能时就需要很多的扩展如分页打印及对打印允许客户有较大的设置自由度时就很麻烦了。我以我这次的功能实现与大家进行探讨。 常见的打印方式有以下三中 第一种对单一控件内容的打印。 private void billtitle_btn_PrintClick(object sender, RoutedEventArgs e) { PrintDialog printDialog new PrintDialog(); if (printDialog.ShowDialog() true) { printDialog.PrintVisual(Mainwindow, 123); } } 其中Mainwindow是控件名也可以是ListView等控件只要把名称传入即可。很简单不过不实用因为这种方法没用自由度是按系统默认进行打印且只能打印在一页上数据多了就不行。 第二种根据PrintDialog进行功能扩展就可以对打印功能在一定程度上扩展。 /// summary/// 打印类/// /summarypublic class PrintService{ public PrintService() { //创建一个PrintDialog的实例 PrintDialog dlg new PrintDialog(); //创建一个PrintDocument的实例 PrintDocument docToPrint new PrintDocument(); //将事件处理函数添加到PrintDocument的PrintPage事件中 docToPrint.PrintPage new System.Drawing.Printing.PrintPageEventHandler (docToPrint_PrintPage); //把PrintDialog的Document属性设为上面配置好的PrintDocument的实例 dlg.Document docToPrint; //根据用户的选择开始打印 if (dlg.ShowDialog() System.Windows.Forms.DialogResult.OK) { docToPrint.Print();//开始打印 } } //设置打印机开始打印的事件处理函数 private void docToPrint_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { e.Graphics.DrawString(Hello, world!, new System.Drawing.Font(Arial, 16, System.Drawing.FontStyle.Regular), System.Drawing.Brushes.Black, 100, 100); }} 在这就可以看出Winform与WPF打印的不同了在WPF在PrintDocument是一个打印方法。WPF有两种打印途径一种是第一种方法中的PrintVisual,另一种就是PrintDocument。 第三种具体步骤如下 1PrintDialog This sample illustrates how to create an instance of a simple PrintDialog and then display it. The sample uses both Extensible Application Markup Language (XAML) and procedural code. 这个示例演示了如何进行一个最简单的打印工作为此需要引入两个dllReachFramework.dll和System.Printing。 InvokePrint方法只是显示了一个PrintDialog打印框并未进行打印工作 PrintDialog pDialog new PrintDialog(); pDialog.PageRangeSelection PageRangeSelection.AllPages; pDialog.UserPageRangeEnabled true; pDialog.ShowDialog(); 有 PrintableAreaHeight和PrintableAreaWidth两个属性分别用来表示可打印区域的高和宽。 而对 PrintDialog的设置可以保存在PrintTicket中下次再打开PrintDialog就不必重复进行设置了。 PrintDialog pDialog new PrintDialog(); PrintTicket pt pDialog.PrintTicket; 同样选择使用哪一台打印机的设置存放在PrintQueue中下次再打开PrintDialog也不用再次设置了。 PrintDialog pDialog new PrintDialog(); PrintQueue pq pDialog.PrintQueue; 如果要把特定的内容打印输出则需要调用PrintDialog的PrintVisual方法 if ((bool)pDialog.ShowDialog().GetValueOrDefault()) { DrawingVisual vis new DrawingVisual(); DrawingContext dc vis.RenderOpen(); dc.DrawLine(new Pen(), new Point(0, 0), new Point(0, 1)); dc.Close(); pDialog.PrintVisual(vis, Hello, world!); } 我们能打印的都是Visual类型的对象其中UIElement派生于 Visual从而我们可以打印所有Panel、控件和其它元素最一般的方法是使用派生于Visual的DrawingVisual类利用它的 RenderOpen方法生成DrawingContext对象为其绘制图形最后使用PrintDialog的PrintVisual方法输出图形 和文字。 注意到pDialog.ShowDialog()返回的是可空类型?bool为此需要使用 GetValueOrDefault将其转为bool值对于null值也会转为false。 2EnumerateSubsetOfPrintQueues EnumerateSubsetOfPrintQueues shows how to use the EnumeratedPrintQueueTypes enumeration to get a subset of available print queues. 这个程序演示了如何得到本地和共享的所有打印机列表。为此需要 使用到EnumeratedPrintQueueTypes枚举中的Local和Shared两个值组合成一个数组 EnumeratedPrintQueueTypes[] enumerationFlags {EnumeratedPrintQueueTypes.Local,EnumeratedPrintQueueTypes.Shared}; 作为参数传递到查询方法GetPrintQueues中 LocalPrintServer printServer new LocalPrintServer(); PrintQueueCollection printQueuesOnLocalServer printServer.GetPrintQueues(enumerationFlags); 接着就可 以对PrintQueueCollection进行遍历了获取每一个的PrintQueue名称和所在位置 foreach (PrintQueue printer in printQueuesOnLocalServer) { Console.WriteLine(tThe shared printer printer.Name is located at printer.Location n); } 下面就看我的方法了先创建一个打印用的类DataPaginator它继承了Document虚基类并进行扩展从而为我们的功能实现做铺垫。 public class DataPaginator : DocumentPaginator { #region 属性及字段 private DataTable dataTable; private Typeface typeFace; private double fontSize; private double margin; private int rowsPerPage; private int pageCount; private Size pageSize; public override Size PageSize { get { return pageSize; } set { pageSize value; PaginateData(); } } public override bool IsPageCountValid { get { return true; } } public override int PageCount { get { return pageCount; } } public override IDocumentPaginatorSource Source { get { return null; } } #endregion #region 构造函数相关方法 //构造函数 public DataPaginator(DataTable dt, Typeface typeface, int fontsize, double margin, Size pagesize) { this.dataTable dt; this.typeFace typeface; this.fontSize fontsize; this.margin margin; this.pageSize pagesize; PaginateData(); } /// summary /// 计算页数pageCount /// /summary private void PaginateData() { //字符大小度量标准 FormattedText ft GetFormattedText(A); //取A的大小计算行高等 //计算行数 rowsPerPage (int)((pageSize.Height - margin * 2) / ft.Height); //预留标题行 rowsPerPage rowsPerPage - 1; pageCount (int)Math.Ceiling((double)dataTable.Rows.Count / rowsPerPage); } /// summary /// 格式化字符 /// /summary private FormattedText GetFormattedText(string text) { return GetFormattedText(text, typeFace); } /// summary /// 按指定样式格式化字符 /// /summary private FormattedText GetFormattedText(string text, Typeface typeFace) { return new FormattedText(text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeFace, fontSize, Brushes.Black); } /// summary /// 获取对应页面数据并进行相应的打印设置 /// /summary public override DocumentPage GetPage(int pageNumber) { //设置列宽 FormattedText ft GetFormattedText(A); Listdouble columns new Listdouble(); int rowCount dataTable.Rows.Count; int colCount dataTable.Columns.Count; double columnWith margin; columns.Add(columnWith); for (int i 1; i colCount; i) { columnWith ft.Width * 15; columns.Add(columnWith); } //获取页面对应行数 int minRow pageNumber * rowsPerPage; int maxRow minRow rowsPerPage; //绘制打印内容 DrawingVisual visual new DrawingVisual(); Point point new Point(margin, margin); using (DrawingContext dc visual.RenderOpen()) { Typeface columnHeaderTypeface new Typeface(typeFace.FontFamily, FontStyles.Normal, FontWeights.Bold, FontStretches.Normal); //获取表头 for (int i 0; i colCount; i) { point.X columns[i]; ft GetFormattedText(dataTable.Columns[i].Caption, columnHeaderTypeface); dc.DrawText(ft, point); } dc.DrawLine(new Pen(Brushes.Black,3), new Point(margin, margin ft.Height), new Point(pageSize.Width - margin, margin ft.Height)); point.Y ft.Height; //获取表数据 for (int i minRow; i maxRow; i) { if (i (rowCount - 1)) break; for (int j 0; j colCount; j) { point.X columns[j]; string colName dataTable.Columns[j].ColumnName; ft GetFormattedText(dataTable.Rows[i][colName].ToString()); dc.DrawText(ft, point); } point.Y ft.Height; } } return new DocumentPage(visual); } #endregion } 又构造函数可知我们需传入一个DataTable这样可打印的内容、样式等就宽泛多了。DataTable可直接获取也可自己根据需要构建我在项目时是根据显示的数据构建一个DataTable。代码如下 /// summary /// 获取要打印的数据 /// /summary private DataTable GetDataTable() { DataTable table new DataTable(Data Table); // Declare variables for DataColumn and DataRow objects. DataColumn column; DataRow row; // Create new DataColumn, set DataType, // ColumnName and add to DataTable. column new DataColumn(); column.DataType Type.GetType(System.Int32); column.ColumnName id; column.Caption 编号; column.ReadOnly true; column.Unique true; // Add the Column to the DataColumnCollection. table.Columns.Add(column); // Create second column. column new DataColumn(); column.DataType Type.GetType(System.String); column.ColumnName Name; column.AutoIncrement false; column.Caption 姓名; column.ReadOnly false; column.Unique false; // Add the column to the table. table.Columns.Add(column); //Create third column column new DataColumn(); column.DataType Type.GetType(System.String); column.ColumnName Age; column.AutoIncrement false; column.Caption 年龄; column.ReadOnly false; column.Unique false; // Add the column to the table. table.Columns.Add(column); //Create forth column column new DataColumn(); column.DataType Type.GetType(System.String); column.ColumnName Pay; column.AutoIncrement false; column.Caption 工资; column.ReadOnly false; column.Unique false; // Add the column to the table. table.Columns.Add(column); // Make the ID column the primary key column. DataColumn[] PrimaryKeyColumns new DataColumn[1]; PrimaryKeyColumns[0] table.Columns[id]; table.PrimaryKey PrimaryKeyColumns; // Instantiate the DataSet variable. //dataSet new DataSet(); // Add the new DataTable to the DataSet. //dataSet.Tables.Add(table); // Create three new DataRow objects and add // them to the DataTable for (int i 0; i 60; i) { row table.NewRow(); row[id] i1; row[Name] zhangsan (i1).ToString(); row[Age] 20 i; row[Pay] 50 * (i 1); table.Rows.Add(row); } return table; } 由此就可以开始打印了 private void BT_MultiPrint_Click(object sender, RoutedEventArgs e) { PrintDialog printDialog new PrintDialog(); if (printDialog.ShowDialog() true) { DataTable dt GetDataTable(); try { DataPaginator dp new DataPaginator(dt, new Typeface(SimSun), 16, 96 * 0.75, new Size(printDialog.PrintableAreaWidth, printDialog.PrintableAreaHeight)); printDialog.PrintDocument(dp, Test Page); } catch { MessageBox.Show(无法打印); } } } 试用后效果还不错。Winform里的打印功能比这强大的多可以将其使用的控件扩展为WPF里的控件或进行别的处理。在这就不论述有兴趣的可以自己去试试。 转载于:https://www.cnblogs.com/weivyuan/archive/2013/01/08/2851411.html