12

What is the best way to print stuff from 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.

John Doe
  • 165
  • 1
  • 4
  • 15
Sam
  • 28,421
  • 49
  • 167
  • 247
  • How much have you already looked at the System.Drawing.Printing namespace? – Joel Coehoorn Dec 16 '08 at 15:12
  • 1
    I've looked in a few ways of printing, but before delving deeply into one I'd like to know more - it's a great waste of time to choose the wrong way to learn more about. – Sam Dec 17 '08 at 12:45

7 Answers7

10

For reports, I use the RDLC control.

For everything else, I use the inherent printing objects within .NET.

Edit The 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.

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.

Here's one tutorial, and a quick Google search for ".NET printing tutorial" returns a bit over 200K results.

Stephen Wrighton
  • 36,783
  • 6
  • 67
  • 86
2

» Sample Code to show basics of Printing in Windows Forms Applications:

    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
    }
S.Serpooshan
  • 7,608
  • 4
  • 33
  • 61
2

We used a set of third party DLLs from PDFSharp who 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:

  • 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.
Robert Gowland
  • 7,677
  • 6
  • 40
  • 58
1

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 seems to give you more choices, but needs a little more learning than 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.

Nelson Reis
  • 4,780
  • 9
  • 43
  • 61
1

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.

Daniel Earwicker
  • 114,894
  • 38
  • 205
  • 284
0

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.

But give us some more information of what you're trying to do, so you can receive better proposals.

Nelson Reis
  • 4,780
  • 9
  • 43
  • 61
  • Oh well, I've got loads of printing stuff coming at me: single pages, long reports, sticky labels, name it, I'll have to print it (soon). So I'd like to get an overview about printing solutions pro and contra. – Sam Dec 16 '08 at 14:18
0

Can Print via 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.

    // 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

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.

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.

You will want to go to NuGet package manager for PDFsharp-MigraDocs (or PDFsharp-MigraDocs-WPF, or PDFsharp-MigraDocs-GDI). MigraDocs is the high-level component that can create documents from elements, without care of if they are pdf or image or what have you. PDFSharp is the component that helps to, i.e., rearrange documents, put multiple documents on a page, and break apart content from one to two pages.

John Doe
  • 165
  • 1
  • 4
  • 15