1

So, I need to print to a laser printer from a windows form application (c#, .net 4) and I've discovered the super "interesting" PrintDocument class and now have code that works, but it looks like this:

private void PrintCollate(vws.custom.production.IndiPackLabel ipl)
    {
        var pd = new PrintDocument();
        pd.DocumentName = "Collate";
        var printerSettings = new System.Drawing.Printing.PrinterSettings();
        printerSettings.PrinterName = "HP LaserJet 4100";
        pd.PrinterSettings = printerSettings;
        pd.PrinterSettings.Copies = 1;
        _currCollate = ipl;
        pd.PrintPage += new PrintPageEventHandler(pd_PrintPage);
        pd.Print();
        _currCollate = null;
    }

    private static vws.custom.production.IndiPackLabel _currCollate;

    public void pd_PrintPage(Object sender, System.Drawing.Printing.PrintPageEventArgs e)
    {
        float linesPerPage = 0;

        //int count = 0;
        float leftMargin = 20;
        float topMargin = 20;

        float yPos = topMargin;


        var printFontNormal = new System.Drawing.Font("consolas", 10);
        var printFontNormalBold = new System.Drawing.Font("consolas", 10, FontStyle.Bold);
        float stdFontHeight = printFontNormal.GetHeight(e.Graphics);

        var printFontSmall = new System.Drawing.Font("consolas", 8);
        float smallFontHeight = printFontSmall.GetHeight(e.Graphics);

        linesPerPage = e.MarginBounds.Height / stdFontHeight;

        e.Graphics.DrawString(("Order: " + _currCollate.OrderDescription).PadRight(91) + "ORD #:" + _currCollate.OrderNumber, printFontNormal, Brushes.Black, leftMargin, yPos);
        yPos += stdFontHeight;

        string customerInfo =  (_currCollate.Customer.FirstName + " " + _currCollate.Customer.LastName).PadRight(90) + " BAG #" + _currCollate.BagNumber;
        e.Graphics.DrawString(customerInfo, printFontNormal, Brushes.Black, leftMargin, yPos);
        yPos += stdFontHeight;
        yPos += stdFontHeight;

        string header = "ITEMNO".PadRight(20) + "ITEM NAME".PadRight(70) + "QTY".PadRight(3);
        e.Graphics.DrawString(header, printFontNormalBold, Brushes.Black, leftMargin, yPos);

        int itemTotal = 0;

        foreach (var item in _currCollate.OrderItems)
        {
            yPos += stdFontHeight;
            string itemLine = item.ItemNo.PadRight(20) + (item.ItemName + " " + item.OptionNames).PadRight(70) + item.Qty.ToString().PadRight(3);
            e.Graphics.DrawString(itemLine, printFontNormal, Brushes.Black, leftMargin, yPos);

            if (item.Notes.Length > 0)
            {
                yPos += stdFontHeight;
                string notesLine = string.Empty.PadRight(20) + item.Notes;
                e.Graphics.DrawString(notesLine, printFontNormal, Brushes.Black, leftMargin, yPos);
            }

            itemTotal += item.Qty;
        }

        yPos += stdFontHeight;
        string footer = "TOTAL ITEMS: ".PadRight(90) + itemTotal;
        e.Graphics.DrawString(footer, printFontNormal, Brushes.Black, leftMargin, yPos);

        e.Graphics.DrawRectangle(new Pen(Color.Black, 2), new Rectangle(20,600,700,500));
    }

There has to be a better way. Especially when I have to change this in 6 months and have to re-figure this out.

I am using Neodynamic's thermal label SDK (http://www.neodynamic.com/ND/ProductsPage.aspx?tabid=107&prod=thermallabel) for printing to Zebra printers and am hoping for a similar API for creating a print document for a laser printer. I'll also need to add bar-code printing to this print document as well, so any tools that include bar-code functionality would be even more helpful.

Any suggestions?

Aaron Barker
  • 706
  • 7
  • 14

1 Answers1

1

If you need your windows form printed exacly as displayed on screen, I would suggest using the DrawToBitmap method. More detail: How to get a screen capture of a .Net control programmatically. This approach works also with composite controls (eg. entire form).

If you need more advanced printing features, I would suggest looking for some "reporting library" for .NET (possibly one of those: Report Viewer / Crystal Reports / SQL Server Reporting Services). Can't give any detailed guidance on this though, since I haven't used any of them myself yet.

Community
  • 1
  • 1
surfen
  • 4,644
  • 3
  • 34
  • 46
  • I think what I am looking for would be similar to a reporting library, but accessible/bound using c#. I'm pretty sure MS Report Viewer and Crystal are dependent on using relational data, but my data is coming from a web service and includes attaching bitmap images on the fly... – Aaron Barker Apr 27 '11 at 03:08
  • 1
    You certainly can fill a report with your data coming from a web service. Have a look at [this walkthrough](http://msdn.microsoft.com/en-us/library/ms251784.aspx#Y114). Basically you create in-memory data source based on any Business Object. I think that attaching bitmap images would also be possible. In fact, creating reports on the fly from code is quite a common scenario, so I'm almost certain it will be feasible with any report library on the market. I've done similar things in java using Jasperreports. – surfen Apr 29 '11 at 22:13