Thursday, January 29, 2009

C# printing

Printing With C# in Visual Studio 2008








The MSDN site for printing graphics is confusing (at least to me), so after some trial and error, here is the result. In this example, the text printing example is extended (slightly) to include graphics printing, as indicated in the text below.





We start with a naked project whose Form's code looks, at the top, like:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
//added from MicroSoft:
using System.IO;
using System.Drawing.Printing;
namespace PrintTest1 {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}


In the designer mode, I added a button which I renamed printButton (to maintain code equivalence with MSDN). I then added the code from


http://msdn.microsoft.com/en-us/library/system.drawing.printing.printdocument(printer).aspx
i.e.,




 // The PrintPage event is raised for each page to be printed.
private void pd_PrintPage(object sender, PrintPageEventArgs ev)
{
if (graphPrint) {//cwd
printDocument1_PrintPage(sender, ev);//cwd
}//cwd
else //cwd
{
float linesPerPage = 0;
float yPos = 0;
int count = 0;
float leftMargin = ev.MarginBounds.Left;
float topMargin = ev.MarginBounds.Top;
string line = null;

// Calculate the number of lines per page.
linesPerPage = ev.MarginBounds.Height /
printFont.GetHeight(ev.Graphics);

// Print each line of the file.
while (count < linesPerPage &&
((line = streamToPrint.ReadLine()) != null))
{
yPos = topMargin + (count *
printFont.GetHeight(ev.Graphics));
ev.Graphics.DrawString(line, printFont, Brushes.Black,
leftMargin, yPos, new StringFormat());
count++;
}

// If more lines exist, print another page.
if (line != null)
ev.HasMorePages = true;
else
ev.HasMorePages = false;
}
}

private void printButton_Click(object sender, EventArgs e)
{
try
{
streamToPrint = new StreamReader
("C:\\isorecorder.log");
try
{
printFont = new Font("Arial", 10);
PrintDocument pd = new PrintDocument();
pd.PrintPage += new PrintPageEventHandler
(this.pd_PrintPage);
pd.Print();
}
finally
{
streamToPrint.Close();
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
//from MicroSoft:
//private System.ComponentModel.Container components; not needed
//private System.Windows.Forms.Button printButton; not needed
private Font printFont;
private StreamReader streamToPrint;
//conversion to dual purpose follows:
public Boolean graphPrint = true;
}
}



This isn't all.



In “Initialize Component” I had to add some code:

 private void InitializeComponent()
{
this.printButton = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// printButton; copied from MicroSoft
//
this.printButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.printButton.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.printButton.Location = new System.Drawing.Point(32, 110);
this.printButton.Name = "printButton";
this.printButton.Size = new System.Drawing.Size(136, 40);
this.printButton.TabIndex = 0;
this.printButton.Text = "Print the file.";
this.printButton.UseVisualStyleBackColor = true;
this.printButton.Click += new System.EventHandler(this.printButton_Click);
//

copied from MSDN at the same site, but lower down in the C# section.

Finally, I added

 //the following comes from MicroSoft virtually intact:
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
e.Graphics.FillRectangle(Brushes.Blue,
new Rectangle(100, 150, 250, 250));
}

which came from http://msdn.microsoft.com/en-us/library/741a0ktc(printer).aspx . The full code now looks like (everything in its proper place):



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
//added from MicroSoft:
using System.IO;
using System.Drawing.Printing;

/*
* this system worked, as drawn from MicroSoft C# help, when printing an
* existing file. Will try and add printing a graphic file. Succeeded via
* and if/then and secondary call (vide infra).
* */

namespace PrintTest1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//the following comes from MicroSoft virtually intact:
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
e.Graphics.FillRectangle(Brushes.Blue,
new Rectangle(100, 150, 250, 250));
}
// The PrintPage event is raised for each page to be printed.
private void pd_PrintPage(object sender, PrintPageEventArgs ev)
{
if (graphPrint) {//cwd
printDocument1_PrintPage(sender, ev);//cwd
}//cwd
else //cwd
{
float linesPerPage = 0;
float yPos = 0;
int count = 0;
float leftMargin = ev.MarginBounds.Left;
float topMargin = ev.MarginBounds.Top;
string line = null;

// Calculate the number of lines per page.
linesPerPage = ev.MarginBounds.Height /
printFont.GetHeight(ev.Graphics);

// Print each line of the file.
while (count < linesPerPage &&
((line = streamToPrint.ReadLine()) != null))
{
yPos = topMargin + (count *
printFont.GetHeight(ev.Graphics));
ev.Graphics.DrawString(line, printFont, Brushes.Black,
leftMargin, yPos, new StringFormat());
count++;
}

// If more lines exist, print another page.
if (line != null)
ev.HasMorePages = true;
else
ev.HasMorePages = false;
}
}

private void printButton_Click(object sender, EventArgs e)
{
try
{
streamToPrint = new StreamReader
("C:\\isorecorder.log");
try
{
printFont = new Font("Arial", 10);
PrintDocument pd = new PrintDocument();
pd.PrintPage += new PrintPageEventHandler
(this.pd_PrintPage);
pd.Print();
}
finally
{
streamToPrint.Close();
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
//from MicroSoft:
//private System.ComponentModel.Container components; not needed
//private System.Windows.Forms.Button printButton; not needed
private Font printFont;
private StreamReader streamToPrint;
//conversion to dual purpose follows:
public Boolean graphPrint = true;
}
}



graphPrint is a boolean which switches between the two modes, and C:\\isorecorder.log happens to be a file located at root which served as a test case text file.



I hope this makes it easier for someone to start printing. The hours I wasted with this is embarrassing.


13 comments:

  1. Thank you very much.
    You are very kind.

    ReplyDelete
  2. Thanks also, just what I needed.

    ReplyDelete
  3. Yay !!!!
    Thank you very very much.

    ReplyDelete
  4. thanks dear.. will u please .. post how to print from database table uisng Data set

    ReplyDelete
  5. Hello,
    Do you happen to know why if you show a Print preview dialog it works out properly, that is you see it on the screen.
    But now when you click on the printer icon,
    it doesn´t print what you see, it just print an empty page.¿?
    Greetings
    jalvarez@zarentia.es

    ReplyDelete
  6. you Rock, it worked out perfectly. you are awesome

    ReplyDelete
  7. hello there...

    i am new to c#

    is there any way to set xoffset and yoffset printing in c#

    as i am creating a form printing application that prints certain input from the windows form to standardized computer fanfold form.

    is there a way to do so?

    ReplyDelete
    Replies
    1. This is exactly what i am looking for do you have that?

      Delete
  8. nice.. this is so helpful.. thanks..

    ReplyDelete
  9. how to print datagrid or panel...whenever these 2 are included...they bceomes hidden

    ReplyDelete
  10. Thanks very much.

    ReplyDelete
  11. Your website layout is hideous but the content rules!

    ReplyDelete