I guess I miss something when it comes to printing files. I read all bytes out of a png image and send them to printer's job stream. However I get bytes printed out and not the image itself. I guess I need proper print format.
This is the link containing code I am using:
http://support.microsoft.com/kb/322091/en
Any ideas?
Sending raw data to a printer doesn't mean just dumping the contents of a file to the printer queue. To send raw data to a printer you would need to be sending PCL, PS or some other equivalent data which tells the printer how to print your document.
You'll likely need to use the System.Drawing.Printing.PrintDocument class.
Edit: There is a good example of how to print an image here on SO:
Printing image with PrintDocument. how to adjust the image to fit paper size
PrintDocument pd = new PrintDocument();
pd.DefaultPageSettings.PrinterSettings.PrinterName = "Printer Name";
pd.DefaultPageSettings.Landscape = true; //or false!
pd.PrintPage += (sender, args) =>
{
Image i = Image.FromFile(#"C:\...\...\image.jpg");
Rectangle m = args.MarginBounds;
if ((double)i.Width / (double)i.Height > (double)m.Width / (double)m.Height) // image is wider
{
m.Height = (int)((double)i.Height / (double)i.Width * (double)m.Width);
}
else
{
m.Width = (int)((double)i.Width / (double)i.Height * (double)m.Height);
}
args.Graphics.DrawImage(i, m);
};
pd.Print();
I think you can use my code here:
//Print Button Event Handeler
private void btnPrint_Click(object sender, EventArgs e)
{
PrintDocument pd = new PrintDocument();
pd.PrintPage += PrintPage;
//here to select the printer attached to user PC
PrintDialog printDialog1 = new PrintDialog();
printDialog1.Document = pd;
DialogResult result = printDialog1.ShowDialog();
if (result == DialogResult.OK)
{
pd.Print();//this will trigger the Print Event handeler PrintPage
}
}
//The Print Event handeler
private void PrintPage(object o, PrintPageEventArgs e)
{
try
{
if (File.Exists(this.ImagePath))
{
//Load the image from the file
System.Drawing.Image img = System.Drawing.Image.FromFile(#"C:\myimage.jpg");
//Adjust the size of the image to the page to print the full image without loosing any part of it
Rectangle m = e.MarginBounds;
if ((double)img.Width / (double)img.Height > (double)m.Width / (double)m.Height) // image is wider
{
m.Height = (int)((double)img.Height / (double)img.Width * (double)m.Width);
}
else
{
m.Width = (int)((double)img.Width / (double)img.Height * (double)m.Height);
}
e.Graphics.DrawImage(img, m);
}
}
catch (Exception)
{
}
}
Related
In C#, I am trying to print an image using PrintDocument class with the below code. The image is of size 1200 px width and 1800 px height. I am trying to print this image in a 4*6 paper using a small zeebra printer. But the program is printing only 4*6 are of the big image. that means it is not adjusting the image to the paper size !
PrintDocument pd = new PrintDocument();
pd.PrintPage += (sender, args) =>
{
Image i = Image.FromFile("C://tesimage.PNG");
Point p = new Point(100, 100);
args.Graphics.DrawImage(i, 10, 10, i.Width, i.Height);
};
pd.Print();
When i print the same image using Window Print (right click and select print, it is scaling automatically to paper size and printing correctly. that means everything came in 4*6 paper.) How do i do the same in my C# program ?
The parameters that you are passing into the DrawImage method should be the size you want the image on the paper rather than the size of the image itself, the DrawImage command will then take care of the scaling for you. Probably the easiest way is to use the following override of the DrawImage command.
args.Graphics.DrawImage(i, args.MarginBounds);
Note: This will skew the image if the proportions of the image are not the same as the rectangle. Some simple math on the size of the image and paper size will allow you to create a new rectangle that fits in the bounds of the paper without skewing the image.
Not to trample on BBoy's already decent answer, but I've done the code that maintains aspect ratio. I took his suggestion, so he should get partial credit here!
PrintDocument pd = new PrintDocument();
pd.DefaultPageSettings.PrinterSettings.PrinterName = "Printer Name";
pd.DefaultPageSettings.Landscape = true; //or false!
pd.PrintPage += (sender, args) =>
{
Image i = Image.FromFile(#"C:\...\...\image.jpg");
Rectangle m = args.MarginBounds;
if ((double)i.Width / (double)i.Height > (double)m.Width / (double)m.Height) // image is wider
{
m.Height = (int)((double)i.Height / (double)i.Width * (double)m.Width);
}
else
{
m.Width = (int)((double)i.Width / (double)i.Height * (double)m.Height);
}
args.Graphics.DrawImage(i, m);
};
pd.Print();
The solution provided by BBoy works fine. But in my case I had to use
e.Graphics.DrawImage(memoryImage, e.PageBounds);
This will print only the form. When I use MarginBounds it prints the entire screen even if the form is smaller than the monitor screen. PageBounds solved that issue. Thanks to BBoy!
You can use my code here
//Print Button Event Handeler
private void btnPrint_Click(object sender, EventArgs e)
{
PrintDocument pd = new PrintDocument();
pd.PrintPage += PrintPage;
//here to select the printer attached to user PC
PrintDialog printDialog1 = new PrintDialog();
printDialog1.Document = pd;
DialogResult result = printDialog1.ShowDialog();
if (result == DialogResult.OK)
{
pd.Print();//this will trigger the Print Event handeler PrintPage
}
}
//The Print Event handeler
private void PrintPage(object o, PrintPageEventArgs e)
{
try
{
if (File.Exists(this.ImagePath))
{
//Load the image from the file
System.Drawing.Image img = System.Drawing.Image.FromFile(#"C:\myimage.jpg");
//Adjust the size of the image to the page to print the full image without loosing any part of it
Rectangle m = e.MarginBounds;
if ((double)img.Width / (double)img.Height > (double)m.Width / (double)m.Height) // image is wider
{
m.Height = (int)((double)img.Height / (double)img.Width * (double)m.Width);
}
else
{
m.Width = (int)((double)img.Width / (double)img.Height * (double)m.Height);
}
e.Graphics.DrawImage(img, m);
}
}
catch (Exception)
{
}
}
Answer:
public void Print(string FileName)
{
StringBuilder logMessage = new StringBuilder();
logMessage.AppendLine(string.Format(CultureInfo.InvariantCulture, "-------------------[ START - {0} - {1} -------------------]", MethodBase.GetCurrentMethod(), DateTime.Now.ToShortDateString()));
logMessage.AppendLine(string.Format(CultureInfo.InvariantCulture, "Parameter: 1: [Name - {0}, Value - {1}", "None]", Convert.ToString("")));
try
{
if (string.IsNullOrWhiteSpace(FileName)) return; // Prevents execution of below statements if filename is not selected.
PrintDocument pd = new PrintDocument();
//Disable the printing document pop-up dialog shown during printing.
PrintController printController = new StandardPrintController();
pd.PrintController = printController;
//For testing only: Hardcoded set paper size to particular paper.
//pd.PrinterSettings.DefaultPageSettings.PaperSize = new PaperSize("Custom 6x4", 720, 478);
//pd.DefaultPageSettings.PaperSize = new PaperSize("Custom 6x4", 720, 478);
pd.DefaultPageSettings.Margins = new Margins(0, 0, 0, 0);
pd.PrinterSettings.DefaultPageSettings.Margins = new Margins(0, 0, 0, 0);
pd.PrintPage += (sndr, args) =>
{
System.Drawing.Image i = System.Drawing.Image.FromFile(FileName);
//Adjust the size of the image to the page to print the full image without loosing any part of the image.
System.Drawing.Rectangle m = args.MarginBounds;
//Logic below maintains Aspect Ratio.
if ((double)i.Width / (double)i.Height > (double)m.Width / (double)m.Height) // image is wider
{
m.Height = (int)((double)i.Height / (double)i.Width * (double)m.Width);
}
else
{
m.Width = (int)((double)i.Width / (double)i.Height * (double)m.Height);
}
//Calculating optimal orientation.
pd.DefaultPageSettings.Landscape = m.Width > m.Height;
//Putting image in center of page.
m.Y = (int)((((System.Drawing.Printing.PrintDocument)(sndr)).DefaultPageSettings.PaperSize.Height - m.Height) / 2);
m.X = (int)((((System.Drawing.Printing.PrintDocument)(sndr)).DefaultPageSettings.PaperSize.Width - m.Width) / 2);
args.Graphics.DrawImage(i, m);
};
pd.Print();
}
catch (Exception ex)
{
log.ErrorFormat("Error : {0}\n By : {1}-{2}", ex.ToString(), this.GetType(), MethodBase.GetCurrentMethod().Name);
}
finally
{
logMessage.AppendLine(string.Format(CultureInfo.InvariantCulture, "-------------------[ END - {0} - {1} -------------------]", MethodBase.GetCurrentMethod().Name, DateTime.Now.ToShortDateString()));
log.Info(logMessage.ToString());
}
}
Agree with TonyM and BBoy - this is the correct answer for original 4*6 printing of label. (args.PageBounds). This worked for me for printing Endicia API service shipping Labels.
private void SubmitResponseToPrinter(ILabelRequestResponse response)
{
PrintDocument pd = new PrintDocument();
pd.PrintPage += (sender, args) =>
{
Image i = Image.FromFile(response.Labels[0].FullPathFileName.Trim());
args.Graphics.DrawImage(i, args.PageBounds);
};
pd.Print();
}
all these answers has the problem, that's always stretching the image to pagesize and cuts off some content at trying this.
Found a little bit easier way.
My own solution only stretch(is this the right word?) if the image is to large, can use multiply copies and pageorientations.
PrintDialog dlg = new PrintDialog();
if (dlg.ShowDialog() == true)
{
BitmapImage bmi = new BitmapImage(new Uri(strPath));
Image img = new Image();
img.Source = bmi;
if (bmi.PixelWidth < dlg.PrintableAreaWidth ||
bmi.PixelHeight < dlg.PrintableAreaHeight)
{
img.Stretch = Stretch.None;
img.Width = bmi.PixelWidth;
img.Height = bmi.PixelHeight;
}
if (dlg.PrintTicket.PageBorderless == PageBorderless.Borderless)
{
img.Margin = new Thickness(0);
}
else
{
img.Margin = new Thickness(48);
}
img.VerticalAlignment = VerticalAlignment.Top;
img.HorizontalAlignment = HorizontalAlignment.Left;
for (int i = 0; i < dlg.PrintTicket.CopyCount; i++)
{
dlg.PrintVisual(img, "Print a Image");
}
}
I have a panel on a tabcontrolpanel that takes up roughly 35% of the screen. I am printing the panel, and it prints the exact size it is on the screen. Is it possible in C# and winforms to scale the image to print on a 8.5x11 peice of paper (even if I have to print it landscape)?
This is my current code --
private void btnPrint_Click(object sender, EventArgs e)
{
PrintDocument doc = new PrintDocument();
doc.PrintPage += new SPrintPageEventHandler(doc_PrintPage);
doc.Print();
}
private void doc_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
Bitmap image = new Bitmap(panelToPrint.Width, panelToPrint.Height, panelToPrint.CreateGraphics());
panelToPrint.DrawToBitmap(image, new Rectangle(0, 0, panelToPrint.Width, panelToPrint.Height));
RectangleF bounds = e.PageSettings.PrintableArea;
float factor = ((float)image.Height / (float)image.Width);
e.Graphics.DrawImage(image, bounds.Left, bounds.Top, bounds.Width, factor * bounds.Width);
}
Edit
I tried to modify my syntax to by default print in landscape mode, but I am still getting the same output as before, just the image printing roughly on the top 15% of the page
private void btnPrint_Click(object sender, EventArgs e)
{
System.Drawing.Printing.PrintDocument doc = new System.Drawing.Printing.PrintDocument();
doc.DefaultPageSettings.Landscape = true;
PrintDialog pdi = new PrintDialog();
pdi.Document = doc;
if (pdi.ShowDialog() == DialogResult.OK)
{
doc.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(doc_PrintPage);
doc.Print();
}
else
{
MessageBox.Show("User cancelled the print job");
}
}
private void doc_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
Bitmap image = new Bitmap(panelToPrint.Width, panelToPrint.Height, panelToPrint.CreateGraphics());
panelToPrint.DrawToBitmap(image, new Rectangle(0, 0, panelToPrint.Width, panelToPrint.Height));
RectangleF bounds = e.PageSettings.PrintableArea;
float factor = ((float)image.Height / (float)image.Width);
e.Graphics.DrawImage(image, bounds.Left, bounds.Top, bounds.Width, factor * bounds.Width);
}
control.DrawToBitmap does exactly that. It prints the control (as you see it on the screen) to a bitmap. If you want to print it in a different size you have to resize the panel before printing.
A better approach is to draw your data that is contained into the panel directly to the page using graphics methods like DrawString etc.
I'm trying to print a very long string using code below but it prints the whole text only in one page. Is there any easy way to print it correctly?
string text="the text has like 1000 words";
System.Drawing.Printing.PrintDocument p = new System.Drawing.Printing.PrintDocument();
p.PrintPage += delegate (object sender1, System.Drawing.Printing.PrintPageEventArgs e1)
{
e1.Graphics.DrawString(text, new System.Drawing.Font("Times New Roman", 12), new System.Drawing.SolidBrush(System.Drawing.Color.Black), new System.Drawing.RectangleF(50, 50, p.DefaultPageSettings.PrintableArea.Width - 50, p.DefaultPageSettings.PrintableArea.Height - 50));
};
try
{
p.Print();
}
catch (Exception ex)
{
throw new Exception("Exception Occured While Printing", ex);
}
I tried to solve it with this article but the method stuck in some loop that I don't know how to fix.
You have to keep in mind that PrintDocument will raise the event PrintPage as long as you tell it there are more pages. It is your task to keep track of what is printed, what needs to printed next and if you need another page or not.
There are several ways to accomplish that. I have chosen in this case to take the content of your text, check how much of it fits on the current page, DrawString that bit and then update my processing string, called remainingtext to be able to repeat for the next Page. The decision if a next page is needed is controlled by setting HasMorepages of the PrintEvent arguments instance to true or false when we're done.
Here is the code:
PrintDocument p = new PrintDocument();
var font = new Font("Times New Roman", 12);
var margins = p.DefaultPageSettings.Margins;
var layoutArea = new RectangleF(
margins.Left,
margins.Top,
p.DefaultPageSettings.PrintableArea.Width - (margins.Left + margins.Right ),
p.DefaultPageSettings.PrintableArea.Height - (margins.Top + margins.Bottom));
var layoutSize = layoutArea.Size;
layoutSize.Height = layoutSize.Height - font.GetHeight(); // keep lastline visible
var brush = new SolidBrush(Color.Black);
// what still needs to be printed
var remainingText = text;
p.PrintPage += delegate (object sender1, PrintPageEventArgs e1)
{
int charsFitted, linesFilled;
// measure how many characters will fit of the remaining text
var realsize = e1.Graphics.MeasureString(
remainingText,
font,
layoutSize,
StringFormat.GenericDefault,
out charsFitted, // this will return what we need
out linesFilled);
// take from the remainingText what we're going to print on this page
var fitsOnPage = remainingText.Substring(0, charsFitted);
// keep what is not printed on this page
remainingText = remainingText.Substring(charsFitted).Trim();
// print what fits on the page
e1.Graphics.DrawString(
fitsOnPage,
font,
brush,
layoutArea);
// if there is still text left, tell the PrintDocument it needs to call
// PrintPage again.
e1.HasMorePages = remainingText.Length > 0;
};
p.Print();
When I hookup an PrintPreviewControl this is the result:
So thanks to rene I figured it out how to print it correctly. I edit his code and the difference here is that the user chooses the paper size and rectangel drawing happens with choosen paper margin size. This is a ready printing method in case you want to use it...
private void Print(string thetext){
try
{
System.Drawing.Printing.PrintDocument p = new System.Drawing.Printing.PrintDocument();
var font = new Font("Times New Roman", 12);
var brush = new System.Drawing.SolidBrush(System.Drawing.Color.Black);
// what still needs to be printed
var remainingText = theText;
p.PrintPage += delegate (object sender1, System.Drawing.Printing.PrintPageEventArgs e1)
{
int charsFitted, linesFilled;
// measure how many characters will fit of the remaining text
var realsize = e1.Graphics.MeasureString(
remainingText,
font,
e1.MarginBounds.Size,
System.Drawing.StringFormat.GenericDefault,
out charsFitted, // this will return what we need
out linesFilled);
// take from the remainingText what we're going to print on this page
var fitsOnPage = remainingText.Substring(0, charsFitted);
// keep what is not printed on this page
remainingText = remainingText.Substring(charsFitted).Trim();
// print what fits on the page
e1.Graphics.DrawString(
fitsOnPage,
font,
brush,
e1.MarginBounds);
// if there is still text left, tell the PrintDocument it needs to call
// PrintPage again.
e1.HasMorePages = remainingText.Length > 0;
};
System.Windows.Forms.PrintDialog pd = new System.Windows.Forms.PrintDialog();
pd.Document = p;
DialogResult result = pd.ShowDialog();
if (result == System.Windows.Forms.DialogResult.OK)
{
p.Print();
}
}catch(Exception e2)
{
System.Windows.MessageBox.Show(e2.Message, "Unable to print",MessageBoxButton.OK);
}
}
Code snippet for "when user clicked 'btnPrint' button, print 'rtbEditor' rich textbox's text.":
private void btnPrint_Click(object sender, EventArgs e) {
var d = new PrintDialog();
d.Document = new PrintDocument();
d.Document.PrintPage += Dd_PrintPage;
remainingText = rtbEditor.Text;
var res = d.ShowDialog();
try { if (res == DialogResult.OK) d.Document.Print(); }
catch { }
}
string remainingText;
private void Dd_PrintPage(object sender, PrintPageEventArgs e){
//this code was for 1 page
//e.Graphics.DrawString(rtbEditor.Text,new Font("Comic Sans MS", 12f),Brushes.Black,new PointF(10,10));
//this is for multiple pages
PrintDocument p = ((PrintDocument)sender);
var font = new Font("Times New Roman", 12);
var margins = p.DefaultPageSettings.Margins;
var layoutArea = new RectangleF(
margins.Left,
margins.Top,
p.DefaultPageSettings.PrintableArea.Width - (margins.Left + margins.Right),
p.DefaultPageSettings.PrintableArea.Height - (margins.Top + margins.Bottom));
var layoutSize = layoutArea.Size;
layoutSize.Height = layoutSize.Height - font.GetHeight(); // keep lastline visible
var brush = new SolidBrush(Color.Black);
int charsFitted, linesFilled;
// measure how many characters will fit of the remaining text
var realsize = e.Graphics.MeasureString(
remainingText,
font,
layoutSize,
StringFormat.GenericDefault,
out charsFitted, // this will return what we need
out linesFilled);
// take from the remainingText what we're going to print on this page
var fitsOnPage = remainingText.Substring(0, charsFitted);
// keep what is not printed on this page
remainingText = remainingText.Substring(charsFitted).Trim();
// print what fits on the page
e.Graphics.DrawString(
fitsOnPage,
font,
brush,
layoutArea);
// if there is still text left, tell the PrintDocument it needs to call
// PrintPage again.
e.HasMorePages = remainingText.Length > 0;
}
I have been trying to print a barcode image via the label printer. but the image that is printing using the SATO CG408 printer is very small. Here is the code as it is currently.
static void Main(string[] args)
{
try
{
PrintDocument pd = new PrintDocument();
pd.DefaultPageSettings.PaperSize = new System.Drawing.Printing.PaperSize("Custom", 100, 77);
//We want potrait.
pd.DefaultPageSettings.Landscape = false;
pd.PrintPage += PrintPage;
pd.Print();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
}
}
private static void PrintPage(object o, PrintPageEventArgs e)
{
//System.Drawing.Image img = System.Drawing.Image.FromFile(#"c:\test\test.png");
//img.RotateFlip(RotateFlipType.Rotate90FlipNone);
//e.Graphics.DrawImage(img,0,0);
int printHeight = 450;
int printWidth = 400;
int leftMargin = 20;
int rightMargin = 0;
System.Drawing.Image img = System.Drawing.Image.FromFile(#"c:\test\test.png");
img.RotateFlip(RotateFlipType.Rotate90FlipNone);
e.Graphics.DrawImage(img, new Rectangle(leftMargin, rightMargin, printWidth, printHeight));
}
Not really sure why the image is displaying small. The image that is being printed is generated at a different server. The image size is 2480px by 1748px.
Can some one please help. Trying to solve this for the past few days. Thanks in advance.
maybe you should set your direction ...
try this:
pd.DefaultPageSettings.Landscape = true;
Try to remove margins
int leftMargin = 0;
int rightMargin = 0;
and check imgage ratio: 2480px / 1748px ~ 1.419, 400px / 450px~ 0,889. So maybe try:
int printHeight = 420;
int printWidth = 596;
The problem was that the printer had the wrong dimensions set up for the paper. Thats why it was printing so small. Feel silly now. Thanks all for help.
I'm trying to print image with this code.
private void Print()
{
PrintDocument printDocument = new PrintDocument();
printDocument.PrintPage += PrintDocument_PrintPage;
PrintPreviewDialog printDialog = new PrintPreviewDialog();
printDialog.Document = printDocument;
DialogResult result = printDialog.ShowDialog();
if (result == DialogResult.OK) printDocument.Print();
printDocument.PrintPage -= PrintDocument_PrintPage;
}
private void PrintDocument_PrintPage(object sender, PrintPageEventArgs e)
{
//e.Graphics.DrawImage(img, e.PageBounds.X, e.PageBounds.Y);
e.Graphics.DrawImage(img, e.PageBounds.X, e.PageBounds.Y,
e.PageBounds.Width, e.PageBounds.Height);
}
When image is small it prints fine, but when its hi-rez (I have image 992*1403) it draws with wrong size.
When I view PreviewDialog or draw it to the pdf file it prints fine, but when I print it on printer it prints wrong sized.
Fixed my problem with this code:
e.Graphics.DrawImage(img, 0, 0, e.PageSettings.PrintableArea.Width, e.PageSettings.PrintableArea.Height);
Just a guess, but how will the application know the PageBounds without knowing what type of paper you are printing on?
Have you tried setting your paper size to a specific size using something like this:
printDocument .DefaultPageSettings.PaperSize =
new PaperSize("Custom", someWidth, someHeight);