fitting rich text box's text into print page c# - c#

I am new in C# and I am trying to print richTextBox's text into a page with size 58x297 but the text always starts from the middle of the page. I checked the printer properties but I couldn't find anything wrong. My aim is to print the text of my rich text box at the very left and top point of the page. I believe the problem is the initial spacing because of the size of my page that is 58x297 spacing is normal for an A4 page but not for mine.
This is the piece of work that I am trying to make work
private void button1_Click(object sender, EventArgs e)
{
PrintDialog printDialog = new PrintDialog();
PrintDocument documentToPrint = new PrintDocument();
printDialog.Document = documentToPrint;
if (printDialog.ShowDialog() == DialogResult.OK)
{
StringReader reader = new StringReader(richTextBox1.Text);
documentToPrint.OriginAtMargins = false;
documentToPrint.PrintPage += new PrintPageEventHandler(Document_Print);
documentToPrint.Print();
}
}
private void Document_Print(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
StringReader reader = new StringReader(richTextBox1.Text);
float LinesPerPage = 0;
float YPosition = 0;
int Count = 0;
float LeftMargin = e.MarginBounds.Left;
float TopMargin = e.MarginBounds.Top;
string Line = null;
Font PrintFont = this.richTextBox1.Font;
SolidBrush PrintBrush = new SolidBrush(Color.Black);
LinesPerPage = e.MarginBounds.Height / PrintFont.GetHeight(e.Graphics);
while (Count < LinesPerPage && ((Line = reader.ReadLine()) != null))
{
YPosition = LeftMargin + (Count * PrintFont.GetHeight(e.Graphics));
e.Graphics.DrawString(Line, PrintFont, PrintBrush, LeftMargin, YPosition, new StringFormat());
Count++;
}
if (Line != null)
{
e.HasMorePages = true;
}
else
{
e.HasMorePages = false;
}
PrintBrush.Dispose();
}
It would definitely be great if you have any ideas about. Thanks a lot ...

Related

Infinite pages generated with e.HasMorePages

I generate several QRCodes and would like to print the barcodes one after another on an A4 size page in Print Preview Control. I also use this control: PrintBar
I calculated, that about 5 QRCodes can be on an A4 format page, so I tried to split with HasMorePages.
Print Preview without HasMorePages: the A4 page with the QRCodes screenshot - the last QRCode should be on the last page.
I added e.HasMorePages and return, but is not working correctly...It counts the pages to infinite and after that crashes.
My code:
BeginPrint
private void printDocument1_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
{
this.currentItem = 0;
}
PrintPage
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
String fontName = "Arial";
Font fontNormal = new Font(fontName, 12, System.Drawing.FontStyle.Regular);
float itemHeight = fontNormal.GetHeight(e.Graphics);
Brush normalColour = Brushes.Black;
float leftMargin = e.MarginBounds.Left;
float topMargin = e.MarginBounds.Top;
float printWidth = e.MarginBounds.Width;
float printHeight = e.MarginBounds.Height;
float rightMargin = leftMargin + printWidth;
float currentPosition = topMargin;
float numberWidth = 70;
float lineWidth = printWidth - numberWidth;
float lineLeft = leftMargin;
float numberLeft = leftMargin + lineWidth;
int items = 0;
foreach (DataRow dr in dt.Rows)
{
if (!dr[4].Equals(""))
items += Convert.ToInt32(dr[4].ToString());
else
items += 0;
}
noOfItems = items;
foreach (DataRow dr in dt.Rows)
{
Bitmap bt = null;
if (!dr[1].Equals(""))
{
if (!dr[4].Equals(""))
{
int nrcodes = Convert.ToInt32(dr[4].ToString());//in the 4th row the value means how many QRCodes should be generated
for (int i = 0; i < nrcodes; i++)
{
if (i % 5 != 0)
{
bt = GenerateQRCODE(dr[1].ToString());//dr[1] QRCode value
e.Graphics.DrawImage(bt, leftMargin, currentPosition, 200, 200);
e.Graphics.DrawString(dr[1].ToString(), fontNormal, normalColour, leftMargin + 40, currentPosition + 180); //dr[1] - text under QR Code
}
else
{
e.HasMorePages = true;
return;
}
currentPosition += 200;
}
}
}
}
// e.HasMorePages = true;
}
Yes, I need to print the same QR Code as many times as in the dr[4] column value. After that the next QR Code the same way.
In this case you need to keep track of the current DataRow and n copy to not repeat the same code for the same row and copy when you set e.HasMorePages = true;. For the copies, request a new page if the bottom of the current output block exceeds the e.MarginBounds.Bottom. To request a new page for each row, uncomment the last lines of the following example.
// +
using System.Drawing.Printing;
// ...
private int curRow = 0;
private int curCopy = 0;
// Or from where you call `.Print();`
// Button.Click event for example.
private void printDocument1_BeginPrint(object sender, PrintEventArgs e)
{
curRow = 0;
curCopy = 0;
}
private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
{
var curY = e.MarginBounds.Y;
using (var fontNormal = new Font("Arial", 12))
using (var sf = new StringFormat())
{
sf.Alignment = sf.LineAlignment = StringAlignment.Center;
int itemHeight = (int)fontNormal.GetHeight(e.Graphics) + 10;
for (int row = curRow; row < dt.Rows.Count; row++)
{
DataRow dr = dt.Rows[row];
if (!string.IsNullOrEmpty(dr.Field<string>(1)) &&
int.TryParse(dr.Field<string>(4)?.ToString(), out int copies))
{
for (int i = curCopy; i < copies; i++)
{
var imgRect = new Rectangle(e.MarginBounds.X, curY, 200, 200);
var labelRect = new Rectangle(
imgRect.X,
imgRect.Bottom,
imgRect.Width,
itemHeight);
if (curY + imgRect.Height + labelRect.Height >= e.MarginBounds.Bottom)
{
curCopy = i;
e.HasMorePages = true;
return;
}
using (var qrImage = GenerateQRCODE(dr[1].ToString()))
e.Graphics.DrawImage(qrImage, imgRect);
e.Graphics.DrawString(dr[1].ToString(),
fontNormal, Brushes.Black,
labelRect, sf);
curY = labelRect.Bottom + 30;
}
}
curRow = row + 1;
curCopy = 0;
// Uncomment if you want to start a new
// page for each row.
//if (row < dt.Rows.Count - 1)
//{
// e.HasMorePages = true;
// break;
//}
}
}

print marigin not set in second page

private StringReader myReader;
private void printToolStripMenuItem_Click(object sender, EventArgs e)
{
printDialog1.Document = printDocument1;
string strText = this.richTextBox1.Text;
myReader = new StringReader(strText);
if (printDialog1.ShowDialog() == DialogResult.OK)
{
printDocument1.Print();
}
}
private void printPrieviewToolStripMenuItem_Click(object sender, EventArgs e)
{
string strText = this.richTextBox1.Text;//read text for richtextbox
myReader = new StringReader(strText);
printPreviewDialog1.Document = printDocument1;
printPreviewDialog1.ShowDialog();
}
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
string line = null;
Font printFont = new System.Drawing.Font("Times New Roman", 8, FontStyle.Regular);
SolidBrush myBrush = new SolidBrush(Color.Black);
float linesPerPage = 0;
float topMargin = 590;
float yPosition = 590;
int count = 0;
float leftMargin = 70;
linesPerPage = e.MarginBounds.Height / printFont.GetHeight(e.Graphics);
while (count < linesPerPage && ((line = myReader.ReadLine()) != null))
{
if (count == 0)
{
yPosition = 590;
topMargin = 590;
}
else
{
yPosition = 100;
topMargin = 100;
}
yPosition = topMargin + (count * printFont.GetHeight(e.Graphics));
e.Graphics.DrawString(line, printFont, myBrush, leftMargin, yPosition, new StringFormat());
count++;
}
if (line != null)
{
e.HasMorePages = true;
}
else
{
e.HasMorePages = false;
myBrush.Dispose();
}
}
}
}
please where is my mistake.i want to print first page is top marigin is 590,and if more pages second page should be print top marigin is 100.
above given code is printing is ok but print marigin is not solved
help me the corection.
You are setting top margin based on count but count is not a page count, it is a line count. you need to keep a page count and use that.
Use a field to hold if it's the first page, remember to set it to true before calling printDocument1_PrintPage e.g:
bool Isfirstpage = true;
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
///.....
if (count == 0 && Isfirstpage)
{
yPosition = 590;
topMargin = 590;
Isfirstpage = false;
}
///....

How do I catch the error from my printer with PrintDocument?

I am using the PrintDocument class to print to my Brother label printer. When I execute the Print() method, the printer starts flashing a red error light, but everything else returns successful.
I can run this same code on my laser printer and everything works fine.
How can I see what is causing the error on my label printer?
Code:
public class Test
{
private Font printFont;
private List<string> _documentLinesToPrint = new List<string>();
public void Run()
{
_documentLinesToPrint.Add("Test1");
_documentLinesToPrint.Add("Test2");
printFont = new Font("Arial", 10);
var pd = new PrintDocument();
pd.DefaultPageSettings.Margins = new Margins(25, 25, 25, 25);
pd.DefaultPageSettings.PaperSize = new PaperSize("Label", 400, 237);
var printerSettings = new System.Drawing.Printing.PrinterSettings();
printerSettings.PrinterName ="Brother QL-570 LE";
pd.PrinterSettings = printerSettings;
pd.PrinterSettings.Copies = 1;
pd.PrintPage += new PrintPageEventHandler(this.pd_PrintPage);
pd.Print();
}
// The PrintPage event is raised for each page to be printed.
private void pd_PrintPage(object sender, PrintPageEventArgs ev)
{
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) && (count < _documentLinesToPrint.Count))
{
line = _documentLinesToPrint[count];
yPos = topMargin + (count *
printFont.GetHeight(ev.Graphics));
ev.Graphics.DrawString(line, printFont, Brushes.Black,
leftMargin, yPos, new StringFormat());
line = null;
count++;
}
// If more lines exist, print another page.
if (line != null)
ev.HasMorePages = true;
else
ev.HasMorePages = false;
}
}
PrintDocument is a very basic API. You get simple generic printing, but it comes at the cost of reduced functionality not specific to the print driver. My HP printer usually gives me a printed error rather than an Exception. Its not surprising to see something similar happening to you.
The blinking is likely a code that you can lookup. If that fails you can try saving to an Image format, PDF or XPS. Or use a 3rd party library or write your own PCL file. There's a ton of options. Creating an output you can view as opposed to one in memory should debugging calculations like margins. You can look at a PDF and see if it looks wacky. Just keep in mind the way it looks on the PC may be slightly different than the output especially when printing near the edges.
I could be completely wrong on this, but my understanding is that when you print with this code, it has nothing to do with the printer itself, but with the operating system. Windows sets up a print queue, places the output in it, and your code returns.
Then Windows takes items off of the queue and sends them through the printer driver and to your printer. If there's an error in printing, it should show up as a failed document in the print queue. I think it's too late to trap the error as an exception at this stage.
Please correct me if I am mistaken.
I would surround your the method bodies using a Try/Catch Block then handle the exception(s) within the catch of each method. As an example:
public class Test
{
private Font printFont;
private List<string> _documentLinesToPrint = new List<string>();
public void Run()
{
try
{
_documentLinesToPrint.Add("Test1");
_documentLinesToPrint.Add("Test2");
printFont = new Font("Arial", 10);
var pd = new PrintDocument();
pd.DefaultPageSettings.Margins = new Margins(25, 25, 25, 25);
pd.DefaultPageSettings.PaperSize = new PaperSize("Label", 400, 237);
var printerSettings = new System.Drawing.Printing.PrinterSettings();
printerSettings.PrinterName = "Brother QL-570 LE";
pd.PrinterSettings = printerSettings;
pd.PrinterSettings.Copies = 1;
pd.PrintPage += new PrintPageEventHandler(this.pd_PrintPage);
pd.Print();
}
catch (InvalidPrinterException exc)
{
// handle your errors here.
}
catch (Exception ex)
{
// handle your errors here.
}
}
// The PrintPage event is raised for each page to be printed.
private void pd_PrintPage(object sender, PrintPageEventArgs ev)
{
try
{
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) && (count < _documentLinesToPrint.Count))
{
line = _documentLinesToPrint[count];
yPos = topMargin + (count *
printFont.GetHeight(ev.Graphics));
ev.Graphics.DrawString(line, printFont, Brushes.Black,
leftMargin, yPos, new StringFormat());
line = null;
count++;
}
// If more lines exist, print another page.
if (line != null)
ev.HasMorePages = true;
else
ev.HasMorePages = false;
}
catch (InvalidPrinterException exc)
{
// handle your errors here.
}
catch (Exception ex)
{
// handle your errors here.
}
}
}

read items from listbox

I have a listbox with 1 or more textfiles, which im going to print as commands.
but I dont know how to make the streamreader read from listbox ?
so far I got this.:
public void OutputBtn_Click(object sender, EventArgs e)
{
PrintDocument PrintD = new PrintDocument();
PrintD.PrintPage += new PrintPageEventHandler(this.PrintDocument_PrintPage);
StreamReader SR = new StreamReader("C:\\myfile.txt");
PrintD.Print();
}
is there enyway I can change "C:\myfile.txt" or do I have to use "foreach" ?
Do you want something like this? I don't fully understand the question
string[] fileEntries = Directory.GetFiles("C:\\temp\\").Where(p =>
p.EndsWith(".txt")).ToArray<string>();
foreach (string fileName in fileEntries)
{
lb.Items.Add(new ListItem(fileName, fileName);
}
Ok so you have the listbox filled with filenames?
private StreamReader sr;
public void OutputBtn_Click(object sender, EventArgs e)
{
foreach(var li in lb.Items)
{
PrintDocument PrintD = new PrintDocument();
PrintD.PrintPage += new PrintPageEventHandler(this.PrintDocument_PrintPage);
sr = new StreamReader(li.ToString());
PrintD.Print();
}
}
private void PrintDocument_PrintPage(object sender, PrintPageEventArgs ev)
{
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) ;
// Iterate over the file, printing each line.
while (count < linesPerPage && ((line = sr.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;
}

Trying to create a new page when horizontal pos. of i extends past right margin

I am trying add a page when horizontal or the x position is greater than a counter in order to keep a right side margin. When I run the code I end up in an infinate loop of hundreds of pages all displaying the same first page graphics. Thinking it might have to do with my lack of understanding HasMorePages. I could use some help. Thanks.
public static class PrintWave
{
public static void PrintPreWave()
{
PrintDocument pd = new PrintDocument();
if (WaveTools.MySettings == null)
{
pd.DefaultPageSettings.Landscape = true;
}
else
{
pd.DefaultPageSettings = WaveTools.MySettings;
}
pd.OriginAtMargins = true;
pd.PrintPage += new PrintPageEventHandler(OnPrintPage);
PrintDialog dlg = new PrintDialog();
PrintPreviewDialog printPreviewDlg = new PrintPreviewDialog();
printPreviewDlg.Document = pd;
Form p = (Form)printPreviewDlg;
p.WindowState = FormWindowState.Maximized;
printPreviewDlg.ShowDialog();
}
private static void OnPrintPage(object sender, PrintPageEventArgs e)
{
string MyTag = string.Empty;
MyTag = WaveActions.ActiveId;
Wave MyWave = WaveHolder.FindWave(MyTag);
int MyCount = 0;
int xOffset = e.MarginBounds.Location.X;
int yOffset = e.MarginBounds.Location.Y;
if (MyWave != null)
{
Graphics g = e.Graphics;
g.SetClip(e.PageBounds);
Pen MyPen = new Pen(WaveTools.WaveColor, WaveTools.PenWidth);
float dx = (float)e.PageBounds.Width / MyWave.NumSamples;
float dy = (float)e.PageBounds.Height / 255;
if (MyWave.Normal == false)
{
g.ScaleTransform(dx, dy);
}
for (int i = 0; i < MyWave.NumSamples - 1; i++)
{
g.DrawLine(MyPen, i, MyWave.Data[i], i + 1, MyWave.Data[i + 1]);
MyCount = MyCount + 1;
if (MyCount > e.MarginBounds.Width)
{
e.HasMorePages = true;
MyCount = 0;
return;
}
else
{
e.HasMorePages = false;
return;
}
}
}
}
}
}
for (int i = 0; i < MyWave.NumSamples - 1; i++)
That's the core problem statement, you start at 0 every time PrintPage gets called. You need to resume where you left off on the previous page. Make the i variable a field of your class instead of a local variable. Implement the BeginPrint event to set it to zero.
The else clause inside the loop need to be deleted.

Categories