I'm trying to print some text data using an event handler, and then print a PDF on the second page.
I'm using pdfium viwer to do this and it works individually. But I'm struggling to combine them.
I need to get the two to print as 2 pages of the same print document, as I want to use a duplex printer to print the pdf on the back. I don't just want to send two individual pages.
Sample code:
To Print PDF:
private void button1_Click(object sender, EventArgs e)
{
string filena = #textBox1.Text;
PrintPDF("M2020", "A4", filena, 1);
}
public bool PrintPDF(string printer, string paperName, string filename, int copies)
{
try
{
// Create the printer settings for our printer
var printerSettings = new PrinterSettings
{
PrinterName = printer,
Copies = (short)copies,
};
// Create our page settings for the paper size selected
var pageSettings = new PageSettings(printerSettings)
{
Margins = new Margins(0, 0, 0, 0),
};
foreach (PaperSize paperSize in printerSettings.PaperSizes)
{
if (paperSize.PaperName == paperName)
{
pageSettings.PaperSize = paperSize;
break;
}
}
// Now print the PDF document
using (var document = PdfDocument.Load(filename))
{
using (var printDocument = document.CreatePrintDocument())
{
printDocument.PrinterSettings = printerSettings;
printDocument.DefaultPageSettings = pageSettings;
printDocument.PrintController = new StandardPrintController();
printDocument.Print();
}
}
return true;
}
catch
{
return false;
}
}
And my original code to print a QR code:
private void Doc_PrintPage(object sender, PrintPageEventArgs e)
{
string s2 = "Modified by: ";
string s6 = "Author: " + author;
string s4 = "Created: " + drawdate;
QRCodeGenerator qrGenerator1 = new QRCodeGenerator();
QRCodeData qrCodeDataPrint = qrGenerator1.CreateQrCode(qrcodedata, QRCodeGenerator.ECCLevel.Q, false, false);
Bitmap qrCodeImagePrint = (new QRCode(qrCodeDataPrint)).GetGraphic(20);
Bitmap bmimg = new Bitmap(this.pictureBox2.Width, this.pictureBox2.Height);
this.pictureBox2.DrawToBitmap(bmimg, new Rectangle(0, 0, this.pictureBox2.Width, this.pictureBox2.Height));
System.Drawing.Font f1 = new System.Drawing.Font("Arial", 5f, FontStyle.Bold, GraphicsUnit.Millimeter);
System.Drawing.Font f2 = new System.Drawing.Font("Arial", 2f, GraphicsUnit.Millimeter);
System.Drawing.Font f3 = new System.Drawing.Font("Arial", 3f, GraphicsUnit.Millimeter);
System.Drawing.Font barc = new System.Drawing.Font("Code39Azalea", 36f, GraphicsUnit.Point);
e.Graphics.PageUnit = GraphicsUnit.Millimeter;
Pen blackPen = new Pen(Color.Black, 1f);
Rectangle rect = new Rectangle(165, 35, 30, 30);
Rectangle qrcodetest = new Rectangle(170, 40, 25, 25);
Rectangle btmimg = new Rectangle(60, 140, 120, 120);
Rectangle combox = new Rectangle(20, 145, 160, 40);
e.Graphics.DrawImage(qrCodeImagePrint, qrcodetest);
e.Graphics.DrawRectangle(blackPen, qrcodetest);
e.Graphics.DrawString(this.procreq, f1, Brushes.Black, new Point(50, 5));
e.Graphics.DrawString(s1, f1, Brushes.Black, new Point(150, 70));
e.Graphics.DrawString(s1z, f2, Brushes.Black, new Point(150, 75));
e.Graphics.DrawString(qrissuedby, f2, Brushes.Black, new Point(20, 264));
e.Graphics.DrawString(s6, f2, Brushes.Black, new Point(20, 267));
e.Graphics.DrawString(s4, f2, Brushes.Black, new Point(20, 270));
e.Graphics.DrawString(s2, f2, Brushes.Black, new Point(20, 273));
e.Graphics.DrawString(s3, f2, Brushes.Black, new Point(20, 276));
e.Graphics.DrawString(s5, f2, Brushes.Black, new Point(20, 279));
e.Graphics.DrawString(this.notebox.Text, f3, Brushes.Black, combox);
e.Graphics.DrawImage(bitmap1, btmimg);
bmimg.Dispose();
bitmap1.Dispose();
}
Any help would be much appreciated!
Thanks
Andrew
Ok, think i was going about that in completely the wrong way. What I eventually did was use the pdfium viewer to render the pdf as a bitmap, and then printed that as the second page.
e.Graphics.PageUnit = GraphicsUnit.Millimeter;
Pen blackPen = new Pen(Color.Black, 1f);
int actualwidth = (int)(e.Graphics.DpiX * 210 / 25.4f);
int actualHeight = (int)(e.Graphics.DpiY * 297 / 25.4f);
using (var pdfDocument = PdfiumViewer.PdfDocument.Load(#textBox1.Text))
{
var bitmapImage = pdfDocument.Render(0, actualwidth, actualHeight, false);
pictureBox1.Image = bitmapImage;
pictureBox1.Image.RotateFlip((RotateFlipType.Rotate90FlipNone));
}
if (pgnum == 1)
{
Debug.WriteLine("firing first page " + pgnum);
Rectangle qrcodetest = new Rectangle(170, 40, 25, 25);
e.Graphics.DrawRectangle(blackPen, qrcodetest);
e.HasMorePages = true;
pgnum++;
Debug.WriteLine(pgnum);
}
else
{
Debug.WriteLine("firing second page " + pgnum);
GraphicsUnit units = GraphicsUnit.Millimeter;
Rectangle srcRect = new Rectangle(0, 0, 199, 281);
//e.Graphics.Q
e.Graphics.Clear(Color.White);
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
e.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
e.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
e.Graphics.DrawImage(pictureBox1.Image, srcRect);
e.HasMorePages = false;
}
This does work.... but the printed version of the PDF is very poor quality. I've tried using interpolation etc.... but doesn't seem to make any difference, so not sure i'm putting it in the right place?
Also, i've tried using the bitmap variable rather than the picturebox image, but it seems to generate the same result. The PDF prints much better.
Thanks
Andrew
Related
I'm writing a simple application in c# .net core 6 and winform to "assemble" some pngs and write some text on it.
This is the Photoshop output. The Title "Baldur the invincible" is wrote in Diablo Light when i'm writing it with DrawString with Font("Diablo", 30, FontStyle.Regular)
and this is my output with the Font.
In photoshop i used Diablo Light font but in the list of system fonts, from C# code, i see just Diablo Regular.. and the result is different.
How i can set the fontweight ?
here some code:
// ---------------------------------------------------------------------------------------------- +
// All TEXT ------------------------------------------------------------------------------------- +
// ---------------------------------------------------------------------------------------------- +
{
//string familyName;
//string familyList = "";
//FontFamily[] fontFamilies;
//InstalledFontCollection installedFontCollection = new InstalledFontCollection();
//fontFamilies = installedFontCollection.Families;
Font title_font = new Font("Diablo", 30, FontStyle.Regular);
Font sub_font = new Font("Diablo", 25, FontStyle.Regular);
List<Font> list_fonts = new List<Font>();
list_fonts.Add(title_font);
list_fonts.Add(sub_font);
RectangleF tit_rect = new RectangleF(165, 70, w - (165 * 2), h);
//RectangleF sub_rect = new RectangleF(165, 82 + 30, w - (165 * 2), h);
var v = m_dict_titles["Title"];
string curr_string = tabbed_value[v].ToUpper();
float offsety = WriteTitleTextf2(map_back, 0, TL(curr_string, false), tit_rect, list_fonts, StringAlignment.Near, 5);
}
public void WriteOnBitmapf(Bitmap bmp, int col, Font font, String text, RectangleF rectf, StringAlignment st_align, float stringi = 0.0f)
{
float size = font.Size;
Graphics g = Graphics.FromImage(bmp);
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
StringFormat format = new StringFormat()
{
Alignment = st_align,
LineAlignment = StringAlignment.Near
};
Brush br = col == 0 ? new SolidBrush(Color.FromArgb(0, 0, 0)) : new SolidBrush(Color.FromArgb(255, 255, 255));
g.DrawString(text, font, br, rectf, format);
g.Flush();
}
I am a PHP developer doing a C# project.
I am busy with a C# winform project.
On printing a document I need to add a page with different content than the first page.
To be clear.I need two pages, each page with its own content.
Currently it is printing 2 pages as expected but with the exact same content on both pages,
Here is an example of what I have currently.
int currentpage = 0;
int numofpages = 2;
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
float pageHeight = e.MarginBounds.Height;
Bitmap bmp = Properties.Resources.someImage;
Image newImage = bmp;
e.Graphics.DrawImage(newImage, 20, 20);
e.Graphics.DrawString("More content", new Font("Verdana", 10, FontStyle.Bold), Brushes.Black, 600, 350);
currentpage++;
if (currentpage < numofpages)
{
e.HasMorePages = true;
Bitmap bmp = Properties.Resources.someOtherImage;
Image newImage = bmp;
e.Graphics.DrawImage(newImage, 20, 20);
e.Graphics.DrawString("Other content", new Font("Verdana", 10, FontStyle.Bold), Brushes.Black, 600, 350);
}
else
{
e.HasMorePages = false;
}
}
Is there a way to create a second page with its own content?
My only current option is to create a second function printDocument2_PrintPage_1 but it is not user-friendly for the end user.
As I said in a comment, it looks like you're trying to render both page's content during a single callback to the event handler. You should instead do something like:
int currentpage = 0;
int numofpages = 2;
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
currentpage++;
if(currentPage==1)
{
Bitmap bmp = Properties.Resources.someImage;
Image newImage = bmp;
e.Graphics.DrawImage(newImage, 20, 20);
e.Graphics.DrawString("More content", new Font("Verdana", 10,
FontStyle.Bold), Brushes.Black, 600, 350);
}
else if(currentPage == 2)
{
Bitmap bmp = Properties.Resources.someOtherImage;
Image newImage = bmp;
e.Graphics.DrawImage(newImage, 20, 20);
e.Graphics.DrawString("Other content", new Font("Verdana", 10,
FontStyle.Bold), Brushes.Black, 600, 350);
}
e.HasMorePages = currentPage < numofpages;
}
I am using Telerik RadBarcode in my Asp.Net web application. See my code to generate the RadBarcode programmatically.
RadBarcode barcode = new RadBarcode();
barcode.Type = BarcodeType.Code128;
barcode.ID = "RadBarcode1";
rcode.Text = "656146114";
barcode.ShowText = true;
barcode.OutputType = BarcodeOutputType.SVG_VML;
Bitmap bitmap1 = new Bitmap(barcode.GetImage());
bitmap1.Save("D:\\" + "\\bmap.jpg");
While saving the barcode as an image the text under the barcode is missing in my case.
We can place a label below the barcode image to show the text and create one new bitmap image which contains the text and barcode data. Refer to the example below;
RadBarcode barcodeRB = new RadBarcode();
barcodeRB.Type = BarcodeType.Code128;
barcodeRB.Text ="123456789";
barcodeRB.ShowText = true;
barcodeRB.OutputType = BarcodeOutputType.SVG_VML;
Bitmap bitmap1 = new Bitmap(barcodeRB.GetImage());
System.Drawing.Image image = barcodeRB.GetImage();
Bitmap barCanvas = new Bitmap(435, 205);
barCanvas.SetResolution(90, 90);
using (Graphics gfx = Graphics.FromImage(barCanvas))
using (SolidBrush brush = new SolidBrush(Color.FromArgb(255, 255, 255)))
{
gfx.FillRectangle(brush, 0, 0, 435, 205);
}
using (Graphics gr = Graphics.FromImage(barCanvas))
{
RectangleF rectf = new RectangleF(150, 170, 300, 50);
gr.DrawImage(image, 20, 20, 400, 150);
gr.DrawString(studentTest.BarcodeString, new Font("GenericSansSerif", 26), Brushes.Black, rectf);
}
barCanvas.Save("D:\" + "\bmap.jpg");
This is my code to create barcode image:
class Program
{
static void Main(string[] args)
{
CreateBarcode("The quick brown fox jumps over the lazy dog".ToUpper());
}
private static void CreateBarcode(string code)
{
var myBitmap = new Bitmap(500, 50);
var g = Graphics.FromImage(myBitmap);
var jgpEncoder = GetEncoder(ImageFormat.Jpeg);
g.Clear(Color.White);
var strFormat = new StringFormat { Alignment = StringAlignment.Center };
g.DrawString(code, new Font("Free 3 of 9", 50), Brushes.Black, new RectangleF(0, 0, 500, 50), strFormat);
var myEncoder = Encoder.Quality;
var myEncoderParameters = new EncoderParameters(1);
var myEncoderParameter = new EncoderParameter(myEncoder, 100L);
myEncoderParameters.Param[0] = myEncoderParameter;
//MemoryStream memoryStrem = new
myBitmap.Save(#"d:\Barcode.jpg", jgpEncoder, myEncoderParameters);
}
private static ImageCodecInfo GetEncoder(ImageFormat format)
{
var codecs = ImageCodecInfo.GetImageDecoders();
foreach (var codec in codecs)
{
if (codec.FormatID == format.Guid)
{
return codec;
}
}
return null;
}
}
This works fine however, this line: g.DrawString(code, new Font("Free 3 of 9", 50), Brushes.Black, new RectangleF(0, 0, 500, 50), strFormat);
as you can see the width here is 500. Now if I specify a big paragraph of text I fear that 500 would not be enough. Is there any way to make this width dynamic based on content?
Its too old to answer, Still am posting as it may help some one. We can create graphics object with a dummy bitmap and try find the length of font, after than re-initialize the bitmap as well as graphics object.
var myBitmap = new Bitmap(1, 1);
Font threeOfNine = new Font("Free 3 of 9", 60, FontStyle.Regular, GraphicsUnit.Point);
var g = Graphics.FromImage(myBitmap);
SizeF dataSize = g.MeasureString(code, threeOfNine);
myBitmap = new Bitmap(myBitmap, dataSize.ToSize());
g = Graphics.FromImage(myBitmap);
I'm dynamically generating image from text, and existing image on my asp.net website.
Here is the code:
protected void Button1_Click(object sender, EventArgs e)
{
var tytul = Request.QueryString["Tytul"];
var tresc = Request.QueryString["Tresc"];
var font = new Font("Verdana", 23);
var brushForeColor = new SolidBrush(Color.Black);
var brushBackColor = new SolidBrush(Color.FromArgb(248, 247, 182));
var test = new Bitmap(450, 60);
var graphicstest = Graphics.FromImage(test);
var width = (int)graphicstest.MeasureString(tresc, font).Width;
var height = (int)graphicstest.MeasureString(tresc, font).Height;
while (width > 450)
{
height = height + 25;
width = width - 450;
}
var heightall = height + 40 + 30 + 100;
var bitmap = new Bitmap(450, heightall);
var graphics = Graphics.FromImage(bitmap);
var displayRectangle = new Rectangle(new Point(0, 0), new Size(450, 40));
graphics.FillRectangle(brushBackColor, displayRectangle);
//Define string format
var format1 = new StringFormat(StringFormatFlags.NoClip);
format1.Alignment = StringAlignment.Center;
var format2 = new StringFormat(format1);
//Draw text string using the text format
graphics.DrawString(tytul, font, brushForeColor, displayRectangle, format2);
// Rysowanie drugiego boxa
brushBackColor = new SolidBrush(Color.FromArgb(253, 253, 202));
font = new Font("Verdana", 18);
displayRectangle = new Rectangle(new Point(0, 40), new Size(450, height + 30));
graphics.FillRectangle(brushBackColor, displayRectangle);
displayRectangle = new Rectangle(new Point(0, 55), new Size(450, height + 15));
graphics.DrawString(tresc, font, brushForeColor, displayRectangle, format2);
graphics.DrawImage(System.Drawing.Image.FromFile(Server.MapPath(".") + "/gfx/layout/podpis.png"), new Point(0, height + 70));
Response.ContentType = "image/png";
bitmap.Save(Response.OutputStream, ImageFormat.Png);
}
As you can see the bitmap is saved and showed on aspx page after postback. What I wanna do is when user click Button1, then image is generated and browser download window pops up, without saving on server or showing on page. How to do this? Please help me.
Cheers.
You need to add a Content-Disposition header.
After you save the file:
Response.AppendHeader("content-disposition", "attachment; filename=podpis.png" );
Response.WriteFile("yourfilepath/podpis.png");
Response.End;