I am trying to print some strings using Graphicss.DrawString(). I have set margins to the printdocument but does not start from the origin of the page. I have set margins to (0,0,0,0) but somehow it prints half centimeter below the top edge of the page. Another thing is that it can print from left edge.
Below is my code.
private void button1_Click(object sender, EventArgs e)
{
////PaperSize pkCustomSize1 = new PaperSize("First custom size", 1020, 3517);
////printDocument1.DefaultPageSettings.PaperSize = pkCustomSize1;
printPreviewDialog1.Document = printDocument1;
printDocument1.PrinterSettings.PrinterName = this.comboBox1.Text;
Margins margins = new Margins(0, 0, 0, 0);
printDocument1.PrinterSettings.DefaultPageSettings.Margins = margins;
printPreviewDialog1.Show();
printDocument1.Print();
}
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
int resX = GetPrinterResolutionX(comboBox1);
int resY = PrnOpra.GetPrinterResolutionY(comboBox1);
Graphics g = e.Graphics;
float scale = resX / ScrnRes;
Bitmap bm = new Bitmap(367, 1205);
g.DrawRectangle(new Pen(Color.Black, 0.5F), panel9.Location.X / 2, panel9.Location.Y / 2, panel9.Width, panel9.Height);
g.DrawImage(bm, 0, 0);
}
What's wrong with code?
You have to set the PrintDocument.OriginAtMargins property to true to consider your margins.
From MSDN,
When OriginAtMargins is true, the Graphics object location takes into account the PageSettings.Margins property value and the printable area of the page
But printing from the exact edge depends on the printable area which is defined by the physical limitations of the printing device. Check the HardMarginX and HardMarginY to get the physical origin of the printer. For more information refer the answer of this question.
Related
I entered a number and generated a barcode. However, I can't print out the size I want from the printer. How can I adjust the dimensions of the label? I am using Godex G300 model printer.
Here is the code I tried :
private void GenerateBarcodeButton_Click(object sender, EventArgs e)
{
if (!String.IsNullOrEmpty(textBox1.Text))
{
Zen.Barcode.Code128BarcodeDraw barcodeDraw = Zen.Barcode.BarcodeDrawFactory.Code128WithChecksum;
pictureBox1.Image = barcodeDraw.Draw(textBox1.Text, 50);
}
else
MessageBox.Show("Please enter the barcode number you want to generate.");
}
public void PrintPicture(object sender, PrintPageEventArgs e)
{
Bitmap bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);
pictureBox1.DrawToBitmap(bmp, new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height));
e.Graphics.DrawImage(bmp, 0, 0);
bmp.Dispose();
}
private void Print_Click(object sender, EventArgs e)
{
PrintDialog pd = new PrintDialog();
PrintDocument pDoc = new PrintDocument();
pDoc.PrintPage += PrintPicture;
pd.Document = pDoc;
if (pd.ShowDialog() == DialogResult.OK)
{
pDoc.Print();
}
}
So a few things to consider (no short answer I'm sorry):
First (optionally) setting the media size of the paper or label in the printer (this can also be set in the Printer Defaults):
pDoc.DefaultPageSettings.PaperSize = new System.Drawing.Printing.PaperSize("Temp", System.Convert.ToInt32((pageSize.Height / (double)96) * 100), System.Convert.ToInt32((pageSize.Width / (double)96) * 100)); //Convert from 96dpi to 100dpi
Then when rendering your image you need to specify the width and height you want to scale and draw at:
e.Graphics.DrawImage(bmp, 0, 0, New System.Drawing.RectangleF(0, 0, width, height), System.Drawing.GraphicsUnit.Pixel)
HOWEVER
I recommend keeping your images original width to avoid blurring which can affect the quality of your barcode and potentially result in it being rejected if used in a commercial environment.
Instead generate a bigger image to begin with.
e.Graphics.DrawImage(bmp, 0, 0, New System.Drawing.RectangleF(0, 0, bmp.Width, bmp.Height), System.Drawing.GraphicsUnit.Pixel)
Lastly you need to consider the DPI of your printer which is 203 DPI
If you try and print a 96dpi image at 203dpi some pixels in your image will span a non-integer number of dots on the printer. When this happens label printers use a process called dithering which will either round partial pixels up/down or alternate rows of pixels to average out. This will result in the lines of your barcode being narrower/wider than they should be or lines with jagged edges.
To avoid this ensure your image DPI matches the DPI of your printer (or your printer DPI can be divided by your image DPI exactly)
Other solutions:
Communicate with the printer directly using a command language it supports (EZPL: https://www.godexprinters.co.uk/desktop/g300)
Buy label printing software such as CodeSoft or BarTender which you design your labels in and interface with in .NET by passing a label file path and set of variable data.
The following code works for me (Honeywell PM43c 203dpi) (note the use of GraphicsUnit.Pixel)
public Form1()
{
InitializeComponent();
pictureBox1.SizeMode = PictureBoxSizeMode.Normal;
pictureBox1.BackColor = Color.White;
}
private void GenerateBarcodeButton_Click(object sender, EventArgs e)
{
if (!String.IsNullOrEmpty(textBox1.Text))
{
pictureBox1.Image = Zen.Barcode.BarcodeDrawFactory.Code128WithChecksum.Draw(textBox1.Text, 50, 2);
}
else
{
MessageBox.Show("Please enter the barcode number you want to generate.");
}
}
public void PrintPicture(object sender, PrintPageEventArgs e)
{
Bitmap bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);
pictureBox1.DrawToBitmap(bmp, new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height));
e.Graphics.DrawImage(bmp, 20, 20, new System.Drawing.RectangleF(0, 0, bmp.Width, bmp.Height), System.Drawing.GraphicsUnit.Pixel);
}
private void PrintButton_Click(object sender, EventArgs e)
{
PrintDialog pd = new PrintDialog();
PrintDocument pDoc = new PrintDocument();
pDoc.PrintPage += PrintPicture;
pd.Document = pDoc;
if (pd.ShowDialog() == DialogResult.OK)
{
pDoc.Print();
}
}
I have successfully printed a windows form, but all the text is slightly blurry. I have concluded that this is a result of the resolution of the screen being much less than the resolution the printer uses. Is there a fundamental flaw in my approach or is there a way to reformat the text prior to printing so that it comes out crisp?
void PrintImage(object o, PrintPageEventArgs e)
{
int x = SystemInformation.WorkingArea.X;
int y = SystemInformation.WorkingArea.Y;
int width = panel1.Width;
int height = panel1.Height;
Rectangle bounds = new Rectangle(x, y, width, height);
Bitmap img = new Bitmap(width, height);
this.DrawToBitmap(img, bounds);
Point p = new Point(100, 100);
e.Graphics.DrawImage(img, p);
}
private void BtnPrint_Click(object sender, EventArgs e)
{
btnPrint.Visible = false;
btnCancel.Visible = false;
if(txtNotes.Text == "Notes:" || txtNotes.Text == "")
{
txtNotes.Visible = false;
}
PrintDocument pd = new PrintDocument();
pd.PrintPage += new PrintPageEventHandler(PrintImage);
pd.Print();
}
Is there a fundamental flaw in my approach [...] ?
Yes.
You take the size of panel1 to calculate the size of the image. Later, you let this draw to the image, but this is the form, not the panel.
What makes you think that SystemInformation.WorkingArea is related to the window you want to print?
You should take a bit more care of disposable objects.
[...] is there a way to reformat the text prior to printing so that it comes out crisp?
There's not a general way which would allow you to scale all other controls as well.
However, instead of blurry text, you can get crisp pixelated text by scaling the bitmap up by a certain factor using the NearestNeighbor mechanism.
Here's the difference in a PDF generated without scaling (left) and a factor of 3 scaling (right) at the same zoom level in Acrobat Reader (click to enlarge):
Here's the scaling code, also without fixing any disposable issues:
this.DrawToBitmap(img, bounds);
Point p = new Point(100, 100);
img = ResizeBitmap(img, 3);
e.Graphics.DrawImage(img, p);
}
private static Bitmap ResizeBitmap(Bitmap source, int factor)
{
Bitmap result = new Bitmap(source.Width*factor, source.Height*factor);
result.SetResolution(source.HorizontalResolution*factor, source.VerticalResolution*factor);
using (Graphics g = Graphics.FromImage(result))
{
g.InterpolationMode = InterpolationMode.NearestNeighbor;
g.DrawImage(source, 0, 0, source.Width*factor, source.Height*factor);
}
return result;
}
I followed the following in post on"Creating a screen magnifier".
Therefore I have this code.
It is not copy & pasted from the post. I have also added a timer so the form is not blank.
However I have found some problems.
It doesn't zoom in very much. I would like to have a larger zoom. An adjustable zoom setting will be optimal, but I can make that myself if I know how to zoom in more.
The center of the form is not always the tip of the cursor like I want it would be. Is there anyway I can Fix this?
Here is the code I have got now.
Graphics g;
Bitmap bmp;
private void Timer1_Tick(object sender, EventArgs e)
{
bmp = new Bitmap(250, 200);
g = this.CreateGraphics();
g = Graphics.FromImage(bmp);
g.CopyFromScreen(MousePosition.X , MousePosition.Y , 0, 0, new Size(300, 300));
pictureBox1.Image = bmp;
}
The results seem to be exactly the same to this software that I found during my research.the link, It takes you to a Japanese webpage.
You're going to have to play around with the various numbers in the example in order to see what effect they have on the output. It'll help to turn them into variables so you can play with them more easily. Here is a good start, no promises that it works, but it'll give you a good place to start experimenting until you get what you want.
Graphics g;
Bitmap bmp;
private void Timer1_Tick(object sender, EventArgs e)
{
var endWidth = 300;
var endHeight = 300;
var scaleFactor = 2; //perhaps get this value from a const, or an on screen slider
var startWidth = endWidth / scaleFactor;
var startHeight = endHeight / scaleFactor;
bmp = new Bitmap(startWidth, startHeight);
g = this.CreateGraphics();
g = Graphics.FromImage(bmp);
var xPos = Math.Max(0, MousePosition.X - (startWidth/2)); // divide by two in order to center
var yPos = Math.Max(0, MousePosition.Y - (startHeight/2));
g.CopyFromScreen(xPos, yPos, 0, 0, new Size(endWidth, endWidth));
pictureBox1.Image = bmp;
}
I have written the below code for printing data from DataGridView in windows c#.
But I want to print one image, text in header and footer.
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
Bitmap bm = new Bitmap(this.SalesGridView.Width, this.SalesGridView.Height);
SalesGridView.DrawToBitmap(bm, new Rectangle(0, 0, this.SalesGridView.Width, this.SalesGridView.Height));
e.Graphics.DrawImage(bm, 0, 0);
}
private void btnPrint_Click(object sender, EventArgs e)
{
printDocument1.Print();
}
Your code as is currently conversation your DataGridView to a Bitmap, and then prints that Bitmap. To print text headers and footers in addition to your DataGridView, you need the Graphics.DrawString() method:
// Create string to draw.
String drawString = "Sample Text";
// Create font and brush.
Font drawFont = new Font("Arial", 16);
SolidBrush drawBrush = new SolidBrush(Color.Black);
// Create point for upper-left corner of drawing.
PointF drawPoint = new PointF(150.0F, 150.0F);
// Draw string to screen.
e.Graphics.DrawString(drawString, drawFont, drawBrush, drawPoint);
}
You will have to adjust the float values for the positioning of each graphic. E.g. your code e.Graphics.DrawImage(bm, 0, 0); prints the Bitmap bm at position (0, 0). So the placement of your header, footer, and DataGridView object positions will need to be changed depending on their size.
If you want to print on multiple pages, you will need to create a loop and add your header and footer to each page programmatically.
In my application i have a chart which is surrounded inside a panel. I added a printdocument component from the toolbox and when i want to print the chart, i am creating a bitmap and i get the panel inside the bitmap (and as a result the chart which is inside the panel). My problem is that when i create the bitmap, when i send it to the printer to print it, it eats up some of the chart from the bottom and from the right side. Below is my code to execute this
private void button1_Click(object sender, EventArgs e)
{
PrintDialog printDialog = new PrintDialog();
printDialog.Document = printDocument1;
printDialog.UseEXDialog = true;
//Get the document
if (DialogResult.OK == printDialog.ShowDialog())
{
printDocument1.DocumentName = "Test Page Print";
printPreviewDialog1.Document = printDocument1;
if (DialogResult.OK == printPreviewDialog1.ShowDialog())
printDocument1.Print();
}
}
This is the button to initialize the print_document. (I added a print preview so that i don't have to print it every time and spent paper and ink)
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
Bitmap bm = new Bitmap(this.panel1.Width, this.panel1.Height);
this.panel1.DrawToBitmap(bm, new Rectangle(50, 50, this.panel1.Width + 50, this.panel1.Height + 50));
e.Graphics.DrawImage(bm, 0, 0);
}
I was thinking that maybe the chart is too big and it doesn't fit in the page but if i save the bitmap. it fits OK inside the page actually there is too much free space on the bottom and right side. (After the draw to bitmap function add
bm.Save(#"c:\LOAN_GRAPH.png");
instead of the draw image and the image is save in c:)
Anybody who can help me i would be truly thankful.
Its working.
I removed the panel and instead, i am creating the rectangle according to my chart.
Bitmap bm = new Bitmap(this.chart1.Width, this.chart1.Height);
this.chart1.DrawToBitmap(bm, new Rectangle(50, 50, this.chart1.Width + 50, this.chart1.Height + 50));
e.Graphics.DrawImage(bm, 0, 0);