日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

WPF中打印问题的探讨[转]

發布時間:2023/12/10 asp.net 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 WPF中打印问题的探讨[转] 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自: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>
/// 打印類
/// </summary>
public 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。

????第三種:具體步驟如下:

  1.PrintDialog

  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.

   這個示例演示了如何進行一個最簡單的打印工作,為此需要引入兩個dll:ReachFramework.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。

   2.EnumerateSubsetOfPrintQueues

   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");
????????????List<double> columns = new List<double>();
????????????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"] = i+1;
????????????????row["Name"] = "zhangsan " + (i+1).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

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的WPF中打印问题的探讨[转]的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。