为 Windows 客户端(不是 Web 应用程序)打印的最佳方式?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/371384/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best way to print for Windows Clients (Not Web Apps)?
提问by Sam
What is the best way to print stuff from c#/.net?
从 c#/.net 打印东西的最佳方法是什么?
The question is in regard to single pages as well as to reports containing lots of pages.
问题是关于单个页面以及包含大量页面的报告。
It would be great to get a list of the most common printing libs containing the main features and gotchas of each of them.
获得最常见的打印库列表会很棒,其中包含每个库的主要功能和陷阱。
[Update] for standard windows clients (or servers), not for web apps, please.
[更新] 适用于标准 Windows 客户端(或服务器),不适用于 Web 应用程序。
采纳答案by Stephen Wrighton
For reports, I use the RDLC control.
对于报告,我使用 RDLC 控件。
For everything else, I use the inherent printing objects within .NET.
对于其他一切,我使用 .NET 中固有的打印对象。
EditThe inherent printing objects are all found in the System.Drawing.Printing namespace. When you use the PrintDialog or the PrintPreviewDialog in a WinForms (or WPF) application, it is to these objects that you're turning over control.
编辑固有的打印对象都可以在 System.Drawing.Printing 命名空间中找到。当您在 WinForms(或 WPF)应用程序中使用 PrintDialog 或 PrintPreviewDialog 时,您正在将控制权移交给这些对象。
The fundamental concept is that you're drawing to the printer. The simplest form of this is:
基本概念是您正在向打印机绘图。最简单的形式是:
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
What's happening here is that when my object (x) is sent the print command, it raises the "PRINT PAGE" event (which is designed to print 1 page at a time). This event then uses the Graphics attribute of the PrintPageEventArgs to draw the relevant string directly to the print spooler.
这里发生的事情是,当我的对象 (x) 被发送打印命令时,它会引发“PRINT PAGE”事件(旨在一次打印 1 页)。此事件然后使用 PrintPageEventArgs 的 Graphics 属性将相关字符串直接绘制到打印假脱机程序。
Here's one tutorial, and a quick Google search for ".NET printing tutorial" returns a bit over 200K results.
这是一个教程,在 Google 上快速搜索“.NET 打印教程”会返回超过 200K 的结果。
回答by Nelson Reis
It depends a lot on the requirements of your application.
这在很大程度上取决于您的应用程序的要求。
Even though it isn't the perfect tool (really far from that), Crystal Reports tends to be a good choice. It gives you the option of getting data directly from a Database or, if you already have a list of objects you want to print, you can pass them to the document and bind the object properties to the labels of the report.
尽管它不是完美的工具(远非如此),但 Crystal Reports 往往是一个不错的选择。它为您提供了直接从数据库获取数据的选项,或者,如果您已经有了要打印的对象列表,您可以将它们传递到文档并将对象属性绑定到报表的标签。
But give us some more information of what you're trying to do, so you can receive better proposals.
但是,请向我们提供有关您正在尝试做什么的更多信息,以便您收到更好的建议。
回答by Robert Gowland
We used a set of third party DLLs from PDFSharpwho in turn use DLLs from MigraDoc. I'm not privy to all the reasons that we went that direction (the decision was made by a senior developer), but I can tell you that:
我们使用了一组来自PDFSharp 的第三方 DLL,而后者又使用来自 MigraDoc 的 DLL。我不知道我们朝那个方向发展的所有原因(这个决定是由一位高级开发人员做出的),但我可以告诉你:
- It seems to be in active development.
- It had most of the features we needed.
- The source code is available. Although it used some patterns and conventions that I hadn't seen before, once I got on to them, it was fairly easy to make the changes. I added support for using the System.Drawing.Image directly rather than as saving files.
- It is not documented well either internally or externally.
- 它似乎正在积极发展。
- 它具有我们需要的大部分功能。
- 源代码可用。尽管它使用了一些我以前从未见过的模式和约定,但是一旦我掌握了它们,就可以很容易地进行更改。我添加了对直接使用 System.Drawing.Image 而不是保存文件的支持。
- 它在内部或外部都没有很好的记录。
回答by Nelson Reis
Loads of stuff, you say. Hum, seems that you should use a solution with a designer, so you should look into Crystal Reports and RDLC. There's also the Reporting Services solution, but in that case you would need a server with SQL Server.
很多东西,你说。嗯,看来你应该使用设计师的解决方案,所以你应该研究一下 Crystal Reports 和 RDLC。还有 Reporting Services 解决方案,但在这种情况下,您需要一台带有 SQL Server 的服务器。
Crystal Reports seems to give you more choices, but needs a little more learning than RDLC.
Crystal Reports 似乎给了你更多的选择,但比 RDLC 需要更多的学习。
I wouldn't recommend you create those in HTML + CSS, because of the limitations and the extra work you would have to throw at it.
我不建议你在 HTML + CSS 中创建那些,因为限制和你必须投入的额外工作。
回答by Daniel Earwicker
If you can build your output as a FlowDocument, you can turn it into XPS easily to get an "electronic" version, and the print the XPS.
如果您可以将输出构建为FlowDocument,则可以轻松将其转换为 XPS 以获得“电子”版本,然后打印 XPS。
回答by S.Serpooshan
? Sample Code to show basics of Printing in Windows Forms Applications:
? 显示 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
}
回答by John Doe
Can Print via Adobe Acrobat
可以通过 Adobe Acrobat 打印
I use the standard libraries such as System.Diagnostics.ProcessStartInfo to use Adobe Acrobat to print a pdf. The end user will not have to interact with the Acrobat GUI, though, annoyingly, the following code still pulls it on-screen for a few seconds.
我使用 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);
}
Can Manipulate via PDFSharp/MigraDoc
可以通过 PDFSharp/MigraDoc 进行操作
I did not read document manipulation into the OP, but I see other answers commenting on the fact. A few StackOverflow Q&As from 2008-2012 (including @Robert Gowland from this question) say that PDFSharp / MigraDoc have poor documentation.
我没有将文档操作读入 OP,但我看到其他答案对这一事实进行了评论。2008-2012 年的一些 StackOverflow 问答(包括来自这个问题的@Robert Gowland)说 PDFSharp / MigraDoc 的文档很差。
In 2018, I have found it to be an easy learning curve, with many samples at the homepage. I read this question this morning to figure out how to print a graph, and now have a button to screen-shot my application and print.
在 2018 年,我发现它是一个简单的学习曲线,主页上有许多示例。我今天早上读了这个问题来弄清楚如何打印图表,现在有一个按钮来截屏我的应用程序并打印。
You will want to go to NuGet package manager for PDFsharp-MigraDocs
(or PDFsharp-MigraDocs-WPF
, or PDFsharp-MigraDocs-GDI
). MigraDocsis the high-level component that can create documents from elements, without care of if they are pdf or image or what have you. PDFSharpis the component that helps to, i.e., rearrange documents, put multiple documents on a page, and break apart content from one to two pages.
您将需要转到 NuGet 包管理器PDFsharp-MigraDocs
(或PDFsharp-MigraDocs-WPF
,或PDFsharp-MigraDocs-GDI
)。MigraDocs是可以从元素创建文档的高级组件,而无需关心它们是 pdf 还是图像或您拥有什么。PDFSharp是帮助重新排列文档、将多个文档放在一个页面上以及将内容从一页拆分到两页的组件。