打印Windows客户端(非Web应用程序)的最佳方式?

从c#/ .net打印东西的最佳方法是什么?

问题在于单页以及包含大量页面的报告。

获得最常见的打印库列表会很棒,其中包含每个打印库的主要function和陷阱。

请更新标准Windows客户端(或服务器),而不是Web应用程序。

对于报告,我使用RDLC控件。

对于其他一切,我使用.NET中的固有打印对象。

编辑固有的打印对象都可以在System.Drawing.Printing命名空间中找到。 当您在WinForms(或WPF)应用程序中使用PrintDialog或PrintPreviewDialog时,您正在翻转这些对象。

基本概念是你正在吸引打印机。 最简单的forms是:

Sub MyMethod() Dim x as New PrintDocument AddHandler x.PrintPage, AddressOf printDoc_PrintPage x.Print End Sub Sub printDoc_PrintPage( sender as Object, e as PrintPageEventArgs) Dim textToPrint as String= ".NET Printing is easy" dim printFont as new Font("Courier New", 12) dim leftMargin as int= e.MarginBounds.Left dim topMargin as int = e.MarginBounds.Top e.Graphics.DrawString(textToPrint, printFont, Brushes.Black, leftMargin, topMargin) End Sub 

这里发生的是当我的对象(x)被发送打印命令时,它会引发“PRINT PAGE”事件(一次打印1页)。 然后,此事件使用PrintPageEventArgs的Graphics属性将相关字符串直接绘制到打印假脱机程序。

这是一个教程 ,快速谷歌搜索“.NET打印教程”返回了超过200K的结果。

我们使用了一组来自PDFSharp的第三方DLL,后者又使用来自MigraDoc的DLL。 我不知道我们走向那个方向的所有原因(决定是由高级开发人员做出的),但我可以告诉你:

  • 它似乎在积极发展。
  • 它具有我们需要的大部分function。
  • 源代码可用。 虽然它使用了我之前从未见过的一些模式和约定,但是一旦我接触到它们,就可以很容易地进行更改。 我添加了对直接使用System.Drawing.Image而不是保存文件的支持。
  • 内部或外部都没有很好地记录。

»示例代码显示Windows窗体应用程序中的打印基础知识:

  using System.Drawing.Printing; PrintDocument printDoc = new PrintDocument(); printDoc.DefaultPageSettings.Landscape = true; printDoc.DefaultPageSettings.Margins.Left = 100; //100 = 1 inch = 2.54 cm printDoc.DocumentName = "My Document Name"; //this can affect name of output PDF file if printer is a PDF printer //printDoc.PrinterSettings.PrinterName = "CutePDF"; printDoc.PrintPage += new PrintPageEventHandler(printDoc_PrintPage); PrintDialog printDialog = new PrintDialog(); printDialog.Document = printDoc; //Document property must be set before ShowDialog() DialogResult dialogResult = printDialog.ShowDialog(); if (dialogResult == DialogResult.OK) { printDoc.Print(); //start the print } void printDoc_PrintPage(object sender, PrintPageEventArgs e) { Graphics g = e.Graphics; string textToPrint = ".NET Printing is easy"; Font font = new Font("Courier New", 12); // e.PageBounds is total page size (does not consider margins) // e.MarginBounds is the portion of page inside margins int x1 = e.MarginBounds.Left; int y1 = e.MarginBounds.Top; int w = e.MarginBounds.Width; int h = e.MarginBounds.Height; g.DrawRectangle(Pens.Red, x1, y1, w, h); //draw a rectangle around the margins of the page, also we can use: g.DrawRectangle(Pens.Red, e.MarginBounds) g.DrawString(textToPrint, font, Brushes.Black, x1, y1); e.HasMorePages = false; //set to true to continue printing next page } 

你说,很多东西。 嗯,似乎你应该使用设计师的解决方案,所以你应该研究Crystal Reports和RDLC。 还有Reporting Services解决方案,但在这种情况下,您需要一台带有SQL Server的服务器。

Crystal Reports似乎为您提供了更多选择,但需要比RDLC更多的学习。

我不建议您在HTML + CSS中创建它们,因为有限制和您需要额外的工作。

如果您可以将输出构建为FlowDocument ,则可以轻松将其转换为XPS以获得“电子”版本,并打印XPS。

这很大程度上取决于您的应用程序的要求。

虽然它不是一个完美的工具(真的很远),Crystal Reports往往是一个不错的选择。 它为您提供了直接从数据库获取数据的选项,或者,如果您已经有要打印的对象列表,则可以将它们传递给文档并将对象属性绑定到报告的标签。

但是,请向我们提供有关您尝试做的更多信息,以便获得更好的建议。

可以通过Adobe Acrobat打印

我使用标准库(如System.Diagnostics.ProcessStartInfo)来使用Adobe Acrobat打印pdf。 最终用户不必与Acrobat GUI进行交互,但令人讨厌的是,下面的代码仍会在屏幕上显示几秒钟。

  // Sample fileName = System.Environment.GetFolderPath( // System.Environment.SpecialFolder.CommonApplicationData) // + @"\MyCompany\MyProject\TestPrint.pdf" private void SendPrintJob(string fileName) { try { // Start by finding Acrobat from the Registry. // This supposedly gets whichever you have of free or paid string processFilename = Microsoft.Win32.Registry.LocalMachine .OpenSubKey("Software") .OpenSubKey("Microsoft") .OpenSubKey("Windows") .OpenSubKey("CurrentVersion") .OpenSubKey("App Paths") .OpenSubKey("AcroRd32.exe") .GetValue(String.Empty).ToString(); ProcessStartInfo info = new ProcessStartInfo(); info.Verb = "print"; info.FileName = processFilename; info.Arguments = String.Format("/p /h {0}", fileName); info.CreateNoWindow = true; info.WindowStyle = ProcessWindowStyle.Hidden; info.UseShellExecute = false; Process p = new Process(); p.StartInfo = info; p.Start(); p.WaitForInputIdle(); // Recommended to add a time-out feature. Mine is coded here. } catch (Exception e) { Console.WriteLine("Error sending print job. " + e.Message); } 

可以通过PDFSharp / MigraDoc进行操作

我没有在OP中阅读文档操作,但我看到其他答案评论了这个事实。 从2008年到2012年的一些StackOverflow问答(包括来自这个问题的@Robert Gowland)说PDFSharp / MigraDoc的文档很差。

在2018年,我发现它是一个简单的学习曲线,在主页上有许多样本。 我今天早上读了这个问题,想弄清楚如何打印图表,现在有一个按钮来屏幕拍摄我的应用程序和打印。

您将需要转到NuGet包管理器获取PDFsharp-MigraDocs (或PDFsharp-MigraDocs-WPF ,或PDFsharp-MigraDocs-GDI )。 MigraDocs是可以从元素创建文档的高级组件,无需关注它们是pdf或image还是您拥有的内容。 PDFSharp是帮助,即重新排列文档,在页面上放置多个文档,以及将内容从一个页面拆分为两个页面的组件。