Pass PaintEventArgs into method - c#

I have the following method in C#:
private string adjustColumnValueLength(String value, int maxLength, PaintEventArgs e)
{
// Set up our string font
System.Drawing.Font printFontText = new System.Drawing.Font("Arial", 12, System.Drawing.FontStyle.Regular);
SizeF stringSize = new SizeF();
string newValue = value;
// Loop until the string fits the size we need
for (int x = value.Length; x >= 0; x--)
{
// Measure the string
newValue = value.Substring(0, x);
stringSize = e.Graphics.MeasureString(newValue, printFontText);
Size roundedSize = Size.Round(stringSize);
if (Int32.Parse(roundedSize.ToString()) <= maxLength)
{
return newValue;
}
}
return newValue;
}
I am calling this from within another method to get the length of a string to match the width in pixels I have to display it, however I have NO idea how I am supposed to pass in the PaintEventArgs. I've tried using System.Windows.Forms.PaintEventArgs but that does not work.
How can this be accomplished?
UPDATE
private void btnPrintTicket_Click(object sender, EventArgs e)
{
// Loop over items in the listScanData object and create a ticket for printing showing
// the Job #, In/Out, Part #, Name, Description and Qty
line = 0;
page = 1;
xCoord = 50;
yCoord = 180;
printTicket = new System.Drawing.Printing.PrintDocument();
printTicket.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(this.ticketData);
PrintDialog printDialog = new PrintDialog();
printDialog.Document = printTicket;
DialogResult result = printDialog.ShowDialog();
if (result == DialogResult.OK)
{
printTicket.Print();
}
}
private void ticketData(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
// Insert code here to render the content we want to print
System.Drawing.Font printFontHeading = new System.Drawing.Font("Arial", 18, System.Drawing.FontStyle.Regular);
System.Drawing.Font printFontSubheading = new System.Drawing.Font("Arial", 16, System.Drawing.FontStyle.Regular);
System.Drawing.Font printFontFooter = new System.Drawing.Font("Arial", 12, System.Drawing.FontStyle.Italic);
System.Drawing.Font printFontLabels = new System.Drawing.Font("Arial", 14, System.Drawing.FontStyle.Underline);
System.Drawing.Font printFontText = new System.Drawing.Font("Arial", 12, System.Drawing.FontStyle.Regular);
// Draw our heading and subheading
string printHeader = "Header 1";
string printSubHeader = "Subheader";
e.Graphics.DrawString(printHeader, printFontHeading, System.Drawing.Brushes.Black, 50, 50);
e.Graphics.DrawString(printSubHeader, printFontSubheading, System.Drawing.Brushes.Black, 50, 80);
Pen pen = new Pen(Color.Gray);
e.Graphics.DrawLine(pen, new Point(50, 110), new Point(800, 110));
// Draw our table headers
string thType = "Type:"; string thName = "Name:"; string thNo = "No:"; string thQty = "Qty:"; string thBackorderQty = "Backorder Qty:";
e.Graphics.DrawString(thType, printFontLabels, System.Drawing.Brushes.Black, 50, 150);
e.Graphics.DrawString(thName, printFontLabels, System.Drawing.Brushes.Black, 200, 150);
e.Graphics.DrawString(thNo, printFontLabels, System.Drawing.Brushes.Black, 400, 150);
e.Graphics.DrawString(thQty, printFontLabels, System.Drawing.Brushes.Black, 550, 150);
e.Graphics.DrawString(thBackorderQty, printFontLabels, System.Drawing.Brushes.Black, 650, 150);
int counter = 0;
// Loop over our data to print it - incrementing our yCoord var by 30 each iteration (so the text doesn't overlap)
for (; line < myGlobals.summaryData.Count; line++ )
{
// If our line var is greater than the data count, we have no more pages to print
if (counter > 26)
{
// Draw our footer on the page
xCoord = 350;
yCoord = 1010;
e.Graphics.DrawString("Page " + page, printFontFooter, System.Drawing.Brushes.Black, xCoord, yCoord);
page++;
// Reset our counter and our x/y coord
counter = 0;
xCoord = 50;
yCoord = 180;
// Indicate we have more to print and return
e.HasMorePages = true;
return;
}
// Assign local vars with the data we need for this iteration
string tdScanType = myGlobals.summaryData[line].ScanType.ToString();
string tdScanName = myGlobals.getProductName(myGlobals.summaryData[line].Barcode.ToString());
//if (tdScanName.Length > 25) { tdScanName = tdScanName.Substring(0, 25); }
tdScanName = adjustColumnValueLength(tdScanName, 200);
string tdScanPartNo = myGlobals.getProductNumber(myGlobals.summaryData[line].Barcode.ToString());
//if (tdScanPartNo.Length > 15) { tdScanPartNo = tdScanPartNo.Substring(0, 15); }
tdScanPartNo = adjustColumnValueLength(tdScanPartNo, 150);
string tdScanQty = myGlobals.summaryData[line].Qty.ToString();
string tdScanBackorderQty = myGlobals.summaryData[line].BackorderQty.ToString();
// Draw the scan type
e.Graphics.DrawString(tdScanType, printFontText, System.Drawing.Brushes.Black, xCoord, yCoord);
// Increment our xCoord
xCoord += 150;
// Draw the scan name
e.Graphics.DrawString(tdScanName, printFontText, System.Drawing.Brushes.Black, xCoord, yCoord);
// Increment our xCoord
xCoord += 200;
// Draw the scan part no
e.Graphics.DrawString(tdScanPartNo, printFontText, System.Drawing.Brushes.Black, xCoord, yCoord);
// Increment our xCoord
xCoord += 150;
// Draw the scan qty
e.Graphics.DrawString(tdScanQty, printFontText, System.Drawing.Brushes.Black, xCoord, yCoord);
// Increment our xCoord
xCoord += 100;
// Draw the scan backorder qty
e.Graphics.DrawString(tdScanBackorderQty, printFontText, System.Drawing.Brushes.Black, xCoord, yCoord);
// Reset our xCoord and increment our yCoord
xCoord = 50;
yCoord += 30;
// Increment our counter
counter++;
}
// Draw our footer on the page
xCoord = 350;
yCoord = 1010;
e.Graphics.DrawString("Page " + page, printFontFooter, System.Drawing.Brushes.Black, xCoord, yCoord);
e.HasMorePages = false;
}
private string adjustColumnValueLength(String value, int maxLength)
{
// Set up our string font
System.Drawing.Font printFontText = new System.Drawing.Font("Arial", 12, System.Drawing.FontStyle.Regular);
Graphics g = this.CreateGraphics();
SizeF stringSize = new SizeF();
string newValue = value;
// Loop until the string fits the size we need
for (int x = value.Length; x >= 0; x--)
{
// Measure the string
newValue = value.Substring(0, x);
//stringSize = TextRenderer.MeasureText(newValue, printFontText);
stringSize = g.MeasureString(newValue, printFontText);
Size roundedSize = Size.Round(stringSize);
if (Int32.Parse(roundedSize.ToString()) <= maxLength)
{
return newValue;
}
}
return newValue;
}
Complete code provided above, I'm trying to call the adjustColumnValueLength from within the ticketData method so that I can substring the value that is being printed to only the width I have available for that column.

You should only call that method from a Paint event handler. I guess you have something in your code like:
private void Control_Paint(object sender, PainEventArgs e) { ... }
You should call your method from there (and nowhere else!):
private void Control_Paint(object sender, PainEventArgs e)
{
adjustColumnValueLength("value", 10, e);
}
If you don't have that, create a event handler:
this.Control.Paint += Control_Paint;
Also read: Custom Control Painting and Rendering.

Related

Change color of only part of text inside a data grid view cell by using c#

I want to change color the given search text in the DataGridView but the data is in Arabic. I have tried CellPainting event to find the bounds of the search text and draw FillRectangle, but I want to change color not highlight for search text.
Here are two figures:
The first figure I want is the same:
The second figure of the form I used:
This is the code that I used
if ((e.RowIndex <= -1 ? false : e.ColumnIndex > -1))
{
string str = txtSearch.Text.Trim();
if (!string.IsNullOrWhiteSpace(str))
{
string[] strArrays = str.Split(new char[] { ' ' });
List<Rectangle> rectangles = new List<Rectangle>();
string[] strArrays1 = strArrays;
for (int i = 0; i < (int)strArrays1.Length; i++)
{
string str1 = strArrays1[i];
string str2 = e.FormattedValue.ToString();
int num = str2.ToLower().IndexOf(str1.ToLower());
if (num >= 0)
{
e.Handled = true;
e.PaintBackground(e.CellBounds, true);
Rectangle y = new Rectangle();
Rectangle cellBounds = e.CellBounds;
y.Y = cellBounds.Y + 2;
cellBounds = e.CellBounds;
y.Height = cellBounds.Height - 5;
string str3 = str2.Substring(0, num);
string str4 = str2.Substring(num, str1.Length);
Graphics graphics = e.Graphics;
Font font = e.CellStyle.Font;
cellBounds = e.CellBounds;
Size size = TextRenderer.MeasureText(graphics, str2, font, cellBounds.Size);
Graphics graphic = e.Graphics;
Font font1 = e.CellStyle.Font;
cellBounds = e.CellBounds;
Size size1 = TextRenderer.MeasureText(graphic, str3, font1, cellBounds.Size);
Graphics graphics1 = e.Graphics;
Font font2 = e.CellStyle.Font;
cellBounds = e.CellBounds;
Size size2 = TextRenderer.MeasureText(graphics1, str4, font2, cellBounds.Size);
cellBounds = e.CellBounds;
int width = (cellBounds.Width - size.Width) / 2;
int x = e.CellBounds.X;
cellBounds = e.CellBounds;
int width1 = x + cellBounds.Width;
y.X = width1 - size1.Width - size2.Width + 5 - width;
y.Width = size2.Width;
rectangles.Add(y);
}
}
if (rectangles.Count > 0)
{
SolidBrush solidBrush = new SolidBrush(Color.Yellow);
foreach (Rectangle rectangle in rectangles)
{
e.Graphics.FillRectangle(solidBrush, rectangle);
}
solidBrush.Dispose();
e.PaintContent(e.CellBounds);
}
}
}
Graphics.FillRectangle will not change the ForeColor.I have modified then CellPainting event.I am using the Graphics.DrawString for changing the ForeColor.
if ((e.RowIndex <= -1 ? false : e.ColumnIndex > -1))
{
string str = txtSearch.Text.Trim();
if (!string.IsNullOrWhiteSpace(str))
{
string[] strArrays = str.Split(new char[] { ' ' });
string[] strArrays1 = strArrays;
for (int i = 0; i < (int)strArrays1.Length; i++)
{
string str1 = strArrays1[i];
string str2 = e.FormattedValue.ToString();
int num = str2.ToLower().IndexOf(str1.ToLower());
if (num >= 0)
{
e.Handled = true;
e.PaintBackground(e.CellBounds, true);
Size size = TextRenderer.MeasureText(e.Graphics, str2, e.CellStyle.Font, e.CellBounds.Size);
Size searchSize = TextRenderer.MeasureText(e.Graphics, str1, e.CellStyle.Font, e.CellBounds.Size);
List<int> indexes = str2.AllIndexesOf(str1).ToList<int>();
string leadingPart = string.Empty;
string printString = string.Empty;
for (int index = 0; index < str2.Length; index++)
{
if (indexes.Contains(index))//Search string starts here
{
leadingPart = str2.Substring(0, index);//leading part of the string
Size leadingSize = TextRenderer.MeasureText(e.Graphics, leadingPart, e.CellStyle.Font, e.CellBounds.Size);
Rectangle rect = new Rectangle(new Point(e.CellBounds.X + leadingSize.Width, e.CellBounds.Y + 4), searchSize);
SolidBrush brush = new SolidBrush(Color.Green);
e.Graphics.DrawString(str1, e.CellStyle.Font, brush, rect);
brush.Dispose();
index += str1.Length - 1;
}
else
{
int nextIndex = indexes.FirstOrDefault(x => x > index);
leadingPart = str2.Substring(0, index);
printString = index < nextIndex ? str2.Substring(index, nextIndex - index) : str2.Substring(index);
Size leadingSize = TextRenderer.MeasureText(e.Graphics, leadingPart, e.CellStyle.Font, e.CellBounds.Size);
Size printSize = TextRenderer.MeasureText(e.Graphics, printString, e.CellStyle.Font, e.CellBounds.Size);
Rectangle rect;
if (index > 0)
rect = new Rectangle(new Point(e.CellBounds.X + leadingSize.Width, e.CellBounds.Y + 4), printSize);//4 is for adjusting the text top position
else
rect = new Rectangle(new Point(e.CellBounds.X, e.CellBounds.Y + 4), printSize);
SolidBrush brush = new SolidBrush(Color.Black);
e.Graphics.DrawString(printString, e.CellStyle.Font, brush, rect);
brush.Dispose();
index += printString.Length - 1;
}
}
}
}
}
}
Note that AllIndexesOf is an extension method for finding all the occurrences of a particular string in a given long string, which I got from this post.
public static IEnumerable<int> AllIndexesOf(this string sourceString, string subString)
{
return Regex.Matches(sourceString, subString,RegexOptions.IgnoreCase).Cast<Match>().Select(m => m.Index);
}
Hope this helps.

Program printing resized images on different OS version

I have a working code, on both the target machine, and my own machine. However, my machine is a W10, and the target is a W7. The code below should draw 5 barcodes on the right half of the page, however, when I use it on the target machine, one of two scenarios happen, depending on how I change the code. If I make the width of the barcode too big, it will go beyond the edge of the page and it will not be readable. If I make the width slightly too small, it resizes the whole barcode, and it becomes to small, again unreadable. I assume that this is a problem with the print drivers in which, they are different for both W10 and W7 (I used the same printer on both machines, same settings as well).
Is there a problem with my code and how do I change it?
private void DocumentDrucker_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
Graphics graphic = e.Graphics;
//SolidBrush brush = new SolidBrush(Color.Black);
Font font = new Font("Courier New", 80, FontStyle.Bold);
Font fontK = new Font("Courier New", 30, FontStyle.Bold);
Font fontKleinst = new Font("Courier New", 15, FontStyle.Bold);
float pageWidth = e.PageSettings.PrintableArea.Width;
float pageHeight = e.PageSettings.PrintableArea.Height;
float fontHeight = font.GetHeight();
int startX = 0;
int startY = 0;
int offsetY = 0;
float imageH = Properties.Resources.pfeilO.Height;
float imageW = Properties.Resources.pfeilO.Width;
graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
//var imagePoint = new Point(Convert.ToInt32(pageWidth * 0.55), offsetY);
var barcodePoint = new Point(Convert.ToInt32(pageWidth * 0.66), 0);
for (; elemente < ZumDrucken.Items.Count; elemente++)
{
var currentItem = ZumDrucken.Items[elemente];
graphic.DrawString(currentItem.Text.Substring(4, 3), fontK, Brushes.Black, startX, startY +offsetY+20);
graphic.DrawString("Typ:"+currentItem.Text.Substring(0,3), fontKleinst, Brushes.Black, startX, (startY + offsetY + 30+fontK.Height));
graphic.DrawString(currentItem.Text.Substring(7), font, Brushes.Black, (startX+75), startY + offsetY);
var currentImage = Properties.Resources.pfeilU;
bool lastCharIsAOne = currentItem.Text[currentItem.Text.Length - 1] == '1';
if (currentItem.Checked == lastCharIsAOne)
{
currentImage = Properties.Resources.pfeilO;
}
graphic.DrawImage(currentImage, Convert.ToInt32((pageWidth * 0.55)), offsetY+20, imageW, imageH);
b.EncodedImage?.Dispose();
//b.Encode(TYPE.CODE128A, "SBD" + currentItem.Text.Substring(0, 3) + currentItem.Text.Substring(4), Color.Black, Color.Transparent,Convert.ToInt32(pageWidth-50), Convert.ToInt32(pageHeight * 0.151));
b.Encode(TYPE.CODE128A, "SBD" + currentItem.Text.Substring(0, 3) + currentItem.Text.Substring(4), Color.Black, Color.Transparent, 570, 135);
barcodePoint.Y = offsetY;
graphic.DrawImage(b.EncodedImage, barcodePoint);
offsetY = offsetY + 163;
if (offsetY >= pageWidth-120)
{
e.HasMorePages = true;
offsetY = 0;
elemente++;
graphic.Dispose();
b.Dispose();
font.Dispose();
fontK.Dispose();
fontKleinst.Dispose();
return;
}
else
{
e.HasMorePages = false;
}
}
graphic.Dispose();
b.Dispose();
font.Dispose();
fontK.Dispose();
fontKleinst.Dispose();
}
Here is also the code where I set all the margins to 0, and change the paper mode to landscape.
private void Drucken_Click(object sender, EventArgs e)
{
DocumentDrucker.DocumentName = "Dokument";
elemente = 0;
DruckDialog.Document = DocumentDrucker;
DocumentDrucker.DefaultPageSettings.Landscape = true;
DocumentDrucker.DefaultPageSettings.Margins.Top = 0;
DocumentDrucker.DefaultPageSettings.Margins.Left = 0;
DocumentDrucker.DefaultPageSettings.Margins.Right = 0;
DocumentDrucker.DefaultPageSettings.Margins.Bottom = 0;
if (DruckDialog.ShowDialog() == DialogResult.OK)
DocumentDrucker.Print();
}

c# nothing printed though there are many data

I have a grid view and I want to print it.
This is my code:
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) {
int rowCounter = 0;
int z = 0;
StringFormat str = new StringFormat();
str.Alignment = StringAlignment.Near;
str.LineAlignment = StringAlignment.Center;
str.Trimming = StringTrimming.EllipsisCharacter;
int width = 500 / (GridView.Columns.Count - 2);
int realwidth = 100;
int height = 40;
int realheight = 100;
for (z = 0; z < GridView.Columns.Count - 1; z++)
{
e.Graphics.FillRectangle(Brushes.AliceBlue, realwidth, realheight, width, height);
e.Graphics.DrawRectangle(Pens.Black, realwidth, realheight, width, height);
e.Graphics.DrawString(GridView.Columns[z].HeaderText, GridView.Font, Brushes.Black, realwidth, realheight);
realwidth = realwidth + width;
}
z = 0;
realheight = realheight + height;
while (rowCounter < GridView.Rows.Count)
{
realwidth = 100;
e.Graphics.FillRectangle(Brushes.AliceBlue, realwidth, realheight, width, height);
e.Graphics.DrawRectangle(Pens.Black, realwidth, realheight, width, height);
e.Graphics.DrawString(GridView.Rows[rowCounter].Cells[0].Value.ToString(), GridView.Font, Brushes.Black, realwidth, realheight);
realwidth = realwidth + width;
}
printDialog1.Document = printDocument1;
printDialog1.ShowDialog();
}
and when the use click on the printing button, I do this:
DialogResult result = printDialog1.ShowDialog();
if (result == DialogResult.OK)
{
this.printDocument1.Print();
}
plus in the construction of the form, I initialze the printing variables like this:
this.printDocument1 = new System.Drawing.Printing.PrintDocument();
this.printDialog1 = new System.Windows.Forms.PrintDialog();
my problem that when I click print, I got empty page though the grid view has more than 320 rows
Update 1
I am following this tutorial http://code.msdn.microsoft.com/windowsdesktop/CSWinFormPrintDataGridView-75864c45
Update 2
The grid view variable is GridView
The code is straightforward I guess
Update 3
I added
++rowCounter;
realheight = realheight + height;
ad the end of the while loop and still the same result
Your code as posted has at least three problems:
In your rows loop you don't advance the rowcounter, which will result in an endless loop.
You also don't advance your realheight variable, which will in result in overprinting all lines
since none of this happens your printDocument1_PrintPage event isn't called; you have probably only copied the code from the example and not actually hooked it up with the printDocument1.
Add to the loop's end:
rowCounter++;
realheight += height;
and in the constructor:
this.printDocument1.PrintPage += this.printDocument1_PrintPage;
Fixing these problems should at least print out something...

How to Print images on paper using PrintDocument

My problem is that is that my code prints the images overlapping each other. I do not know how to change the x and y positions. The printer should print 3 images per row and then move to the next row.
private void panel1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
for (int serial = 0; serial < SaveBeforePrint.Count; serial++)
{
String intercharacterGap = "0";
String str = '*' + SaveBeforePrint[serial].ToUpper() + '*';
int strLength = str.Length;
for (int i = 0; i < SaveBeforePrint[serial].Length; i++)
{
string barcodestring = SaveBeforePrint[serial].ToUpper();
if (alphabet39.IndexOf(barcodestring[i]) == -1 || barcodestring[i] == '*')
{
e.Graphics.DrawString("INVALID BAR CODE TEXT", Font, Brushes.Red, 10, 10);
return;
}
}
String encodedString = "";
for (int i = 0; i < strLength; i++)
{
if (i > 0)
encodedString += intercharacterGap;
encodedString += coded39Char[alphabet39.IndexOf(str[i])];
}
int encodedStringLength = encodedString.Length;
int widthOfBarCodeString = 0;
double wideToNarrowRatio = 3;
if (align != AlignType.Left)
{
for (int i = 0; i < encodedStringLength; i++)
{
if (encodedString[i] == '1')
widthOfBarCodeString += (int)(wideToNarrowRatio * (int)weight);
else
widthOfBarCodeString += (int)weight;
}
}
int x = 0;
int wid = 0;
int yTop = 0;
SizeF hSize = e.Graphics.MeasureString(headerText, headerFont);
SizeF fSize = e.Graphics.MeasureString(code, footerFont);
int headerX = 0;
int footerX = 0;
int printonpage = 0;
if (align == AlignType.Left)
{
x = leftMargin;
headerX = leftMargin;
footerX = leftMargin;
}
else if (align == AlignType.Center)
{
x = (Width - widthOfBarCodeString) / 2;
headerX = (Width - (int)hSize.Width) / 2;
footerX = (Width - (int)fSize.Width) / 2;
}
else
{
x = Width - widthOfBarCodeString - leftMargin;
headerX = Width - (int)hSize.Width - leftMargin;
footerX = Width - (int)fSize.Width - leftMargin;
}
if (showHeader)
{
yTop = (int)hSize.Height + topMargin;
e.Graphics.DrawString(headerText, headerFont, Brushes.Black, headerX, topMargin);
}
else
{
yTop = topMargin;
}
for (int i = 0; i < encodedStringLength; i++)
{
if (encodedString[i] == '1')
wid = (int)(wideToNarrowRatio * (int)weight);
else
wid = (int)weight;
e.Graphics.FillRectangle(i % 2 == 0 ? Brushes.Black : Brushes.White, x, yTop, wid, height);
x += wid;
}
yTop += height;
if (showFooter)
e.Graphics.DrawString(SaveBeforePrint[serial], footerFont, Brushes.Black, footerX, yTop);
}
}
Desired output :
I am getting :
As you can see the last digit is overlapping. I want to draw it next to the previous one
I have observed the code and found the issue.. in panel1_print u are not incrementing the values properly..
I have made the required changes now u will get the 4 bar in a line and 5th one in another line - check the attached image.
just replace ur panel1_Paint with this new code thats it you can find the changes..
I have marked them as
//start changes by Deepak
..
..
..
//end changes by Deepak
and also declare two variables loopValX and loopValY as int
here is the code..
private void panel1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
int loopValX = 0;
int loopValY = -150;
for (int serial = 0; serial < SaveBeforePrint.Count; serial++)
{
String intercharacterGap = "0";
String str = '*' + SaveBeforePrint[serial].ToUpper() + '*';
int strLength = str.Length;
for (int i = 0; i < SaveBeforePrint[serial].Length; i++)
{
string barcodestring = SaveBeforePrint[serial].ToUpper();
if (alphabet39.IndexOf(barcodestring[i]) == -1 || barcodestring[i] == '*')
{
e.Graphics.DrawString("INVALID BAR CODE TEXT", Font, Brushes.Red, 10, 10);
return;
}
}
String encodedString = "";
for (int i = 0; i < strLength; i++)
{
if (i > 0)
encodedString += intercharacterGap;
encodedString += coded39Char[alphabet39.IndexOf(str[i])];
}
int encodedStringLength = encodedString.Length;
int widthOfBarCodeString = 0;
double wideToNarrowRatio = 3;
if (align != AlignType.Left)
{
for (int i = 0; i < encodedStringLength; i++)
{
if (encodedString[i] == '1')
widthOfBarCodeString += (int)(wideToNarrowRatio * (int)weight);
else
widthOfBarCodeString += (int)weight;
}
}
SizeF hSize = e.Graphics.MeasureString(headerText, headerFont);
SizeF fSize = e.Graphics.MeasureString(SaveBeforePrint[serial], footerFont);
int headerX = 0;
int footerX = 0;
if (align == AlignType.Left)
{
x = leftMargin;
headerX = leftMargin;
footerX = leftMargin;
}
else if (align == AlignType.Center)
{
x = (Width - widthOfBarCodeString) / 2;
headerX = (Width - (int)hSize.Width) / 2;
footerX = (Width - (int)fSize.Width) / 2;
}
else
{
x = Width - widthOfBarCodeString - leftMargin;
headerX = Width - (int)hSize.Width - leftMargin;
footerX = Width - (int)fSize.Width - leftMargin;
}
if (showHeader)
{
y = (int)hSize.Height + topMargin;
e.Graphics.DrawString(headerText, headerFont, Brushes.Black, headerX, topMargin);
}
else
{
y = topMargin;
}
//start changes by Deepak
if (serial % 4 == 0)
{
loopValX = 0;
loopValY += 150;
}
else
{
loopValX += 150;
}
x += loopValX;
y += loopValY;
footerX += loopValX;
//end changes by Deepak
for (int i = 0; i < encodedStringLength; i++)
{
if (encodedString[i] == '1')
wid = (int)(wideToNarrowRatio * (int)weight);
else
wid = (int)weight;
e.Graphics.FillRectangle(i % 2 == 0 ? Brushes.Black : Brushes.White, x, y, wid, height);
x += wid;
}
y += height;
if (showFooter)
e.Graphics.DrawString(SaveBeforePrint[serial], footerFont, Brushes.Black, footerX, y);
}
}
You Should do it with the help of a DataGridView (That Contains Images in a Column).
The Images Will Then Print in each new row or column (by modifying as your desire)
The Following Class will do your work by passing it the whole DataGridView And Header in its constructor.
using System;
using System.Collections;
using System.Drawing;
using System.Drawing.Printing;
using System.Windows.Forms;
using System.Linq;
namespace Waqas
{
internal class ClsPrint
{
#region Variables
private int iCellHeight = 0; //Used to get/set the datagridview cell height
private int iTotalWidth = 0; //
private int iRow = 0; //Used as counter
private bool bFirstPage = false; //Used to check whether we are printing first page
private bool bNewPage = false; // Used to check whether we are printing a new page
private int iHeaderHeight = 0; //Used for the header height
private StringFormat strFormat; //Used to format the grid rows.
private ArrayList arrColumnLefts = new ArrayList(); //Used to save left coordinates of columns
private ArrayList arrColumnWidths = new ArrayList(); //Used to save column widths
private PrintDocument _printDocument = new PrintDocument();
private DataGridView gw = new DataGridView();
private string _ReportHeader;
#endregion
public ClsPrint(DataGridView gridview, string ReportHeader)
{
_printDocument.DefaultPageSettings.Landscape = true;
_printDocument.DefaultPageSettings.PaperSize.RawKind = (int)PaperKind.A4;
_printDocument.DefaultPageSettings.Margins = new Margins(30, 30, 30, 30);
//_printDocument.DefaultPageSettings.PaperSize.PaperName = "A4";
_printDocument.PrintPage += new PrintPageEventHandler(_printDocument_PrintPage);
_printDocument.BeginPrint += new PrintEventHandler(_printDocument_BeginPrint);
gw = gridview;
_ReportHeader = ReportHeader;
}
public void PrintForm()
{
//Open the print preview dialog
PrintPreviewDialog objPPdialog = new PrintPreviewDialog();
objPPdialog.Document = _printDocument;
objPPdialog.ShowIcon = false;
objPPdialog.Text = "Print Preview";
objPPdialog.WindowState = FormWindowState.Maximized;
objPPdialog.ShowDialog();
}
private void _printDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
//try
//{
//Set the left margin
int iLeftMargin = e.MarginBounds.Left;
//Set the top margin
int iTopMargin = e.MarginBounds.Top;
//Whether more pages have to print or not
bool bMorePagesToPrint = false;
int iTmpWidth = 0;
//For the first page to print set the cell width and header height
if (bFirstPage)
{
foreach (DataGridViewColumn GridCol in gw.Columns)
{
iTmpWidth = ((int) (Math.Floor((double) ((double) GridCol.Width/
(double) iTotalWidth*(double) iTotalWidth*
((double) e.MarginBounds.Width/(double) iTotalWidth)))));
iHeaderHeight = (int) (e.Graphics.MeasureString(GridCol.HeaderText,
GridCol.InheritedStyle.Font, iTmpWidth).Height) + 60;
// Save width and height of headers
arrColumnLefts.Add(iLeftMargin);
arrColumnWidths.Add(iTmpWidth);
iLeftMargin += iTmpWidth;
}
}
//Loop till all the grid rows not get printed
while (iRow <= gw.Rows.Count - 1)
{
DataGridViewRow GridRow = gw.Rows[iRow];
//Set the cell height
iCellHeight = GridRow.Height + 30;
int iCount = 0;
//Check whether the current page settings allows more rows to print
if (iTopMargin + iCellHeight >= e.MarginBounds.Height + e.MarginBounds.Top)
{
bNewPage = true;
bFirstPage = false;
bMorePagesToPrint = true;
break;
}
else
{
if (bNewPage)
{
//Draw Header
e.Graphics.DrawString(_ReportHeader,
new Font("Calibri Light", 20, FontStyle.Bold),
new SolidBrush(Color.Black), e.MarginBounds.Left,
e.MarginBounds.Top+20 - e.Graphics.MeasureString(_ReportHeader,
new Font(gw.Font, FontStyle.Bold),
e.MarginBounds.Width).Height - 13);
String strDate = DateTime.Now.ToString("dd-MMM-yy hh:mm tt");
//Draw Date
e.Graphics.DrawString(strDate,
new Font("Calibri Light", 12, FontStyle.Bold), Brushes.Black,
e.MarginBounds.Left-20 +
(e.MarginBounds.Width - e.Graphics.MeasureString(strDate,
new Font(gw.Font, FontStyle.Bold),
e.MarginBounds.Width).Width),
e.MarginBounds.Top+30 - e.Graphics.MeasureString(_ReportHeader,
new Font(new Font(gw.Font, FontStyle.Bold),
FontStyle.Bold), e.MarginBounds.Width).Height - 13);
//Draw Columns
iTopMargin = e.MarginBounds.Top+30;
DataGridViewColumn[] _GridCol = new DataGridViewColumn[gw.Columns.Count];
int colcount = 0;
//Convert ltr to rtl
foreach (DataGridViewColumn GridCol in gw.Columns)
{
_GridCol[colcount++] = GridCol;
}
for (int i =0; i <= (_GridCol.Count() - 1); i++)
{
e.Graphics.FillRectangle(new SolidBrush(Color.Gainsboro),
new Rectangle((int) arrColumnLefts[iCount], iTopMargin,
(int) arrColumnWidths[iCount], iHeaderHeight));
e.Graphics.DrawRectangle(new Pen(Color.Black),
new Rectangle((int) arrColumnLefts[iCount], iTopMargin,
(int) arrColumnWidths[iCount], iHeaderHeight));
e.Graphics.DrawString(_GridCol[i].HeaderText,
new Font("Calibri Light", 12, FontStyle.Bold),
new SolidBrush(Color.Black),
new RectangleF((int) arrColumnLefts[iCount], iTopMargin,
(int) arrColumnWidths[iCount], iHeaderHeight), strFormat);
iCount++;
}
bNewPage = false;
iTopMargin += iHeaderHeight;
}
iCount = 0;
DataGridViewCell[] _GridCell = new DataGridViewCell[GridRow.Cells.Count];
int cellcount = 0;
//Convert ltr to rtl
foreach (DataGridViewCell Cel in GridRow.Cells)
{
_GridCell[cellcount++] = Cel;
}
//Draw Columns Contents
for (int i =0; i <=(_GridCell.Count() - 1); i++)
{
if (_GridCell[i].Value != null)
{
if (_GridCell[i].GetType() != typeof (DataGridViewImageCell))
{
e.Graphics.DrawString(_GridCell[i].FormattedValue.ToString(),
new Font("Calibri Light", 10),
new SolidBrush(Color.Black),
new RectangleF((int) arrColumnLefts[iCount],
(float) iTopMargin,
(int) arrColumnWidths[iCount], (float) iCellHeight),
strFormat);
}
else
{
Image img = Common.byteArrayToImage((byte[]) _GridCell[i].Value);
Rectangle m = new Rectangle((int) arrColumnLefts[iCount],iTopMargin,
(int) arrColumnWidths[iCount], iCellHeight);
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);
}
}
//Drawing Cells Borders
e.Graphics.DrawRectangle(new Pen(Color.Black),
new Rectangle((int) arrColumnLefts[iCount], iTopMargin,
(int) arrColumnWidths[iCount], iCellHeight));
iCount++;
}
}
iRow++;
iTopMargin += iCellHeight;
}
//If more lines exist, print another page.
if (bMorePagesToPrint)
e.HasMorePages = true;
else
e.HasMorePages = false;
//}
//catch (Exception exc)
//{
// KryptonMessageBox.Show(exc.Message, "Error", MessageBoxButtons.OK,
// MessageBoxIcon.Error);
//}
}
private void _printDocument_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
{
try
{
strFormat = new StringFormat();
strFormat.Alignment = StringAlignment.Center;
strFormat.LineAlignment = StringAlignment.Center;
strFormat.Trimming = StringTrimming.EllipsisCharacter;
arrColumnLefts.Clear();
arrColumnWidths.Clear();
iCellHeight = 0;
iRow = 0;
bFirstPage = true;
bNewPage = true;
// Calculating Total Widths
iTotalWidth = 0;
foreach (DataGridViewColumn dgvGridCol in gw.Columns)
{
iTotalWidth += dgvGridCol.Width;
}
}
catch (Exception ex)
{
KryptonMessageBox.Show(ex.Message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
as
ClsPrint _ClsPrint = new ClsPrint(myDataGridView, "MyHeader");
_ClsPrint.PrintForm();
Your position variables are being declared inside the loop, meaning that they are reset for each pass through the loop. Keep position variables for X and Y outside of the loop over serial and adjust it for the total width (and height, if you start a new row of barcodes) of each barcode.

How to print one large image in many pages?

I want to print one tall (long) image in many pages. So in every page, I take a suitable part from the image and I draw it in the page.
the problem is that I have got the image shrunk (its shape is compressed) in the page,so I added an scale that its value is 1500 .
I think that I can solve the problem if I knew the height of the page (e.Graphics) in pixels.
to convert Inches to Pixel, Do I have to multiply by (e.Graphics.DpiX = 600) or multiply by 96 .
void printdocument_PrintPage(object sender, PrintPageEventArgs e)
{
if (pageImage == null)
return;
e.Graphics.PageUnit = GraphicsUnit.Pixel;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
float a = (e.MarginBounds.Width / 100) * e.Graphics.DpiX;
float b = ((e.MarginBounds.Height / 100) * e.Graphics.DpiY);
int scale = 1500;
scale = 0; //try to comment this
RectangleF srcRect = new RectangleF(0, startY, pageImage.Width, b - scale);
RectangleF destRect = new RectangleF(0, 0, a, b);
e.Graphics.DrawImage(pageImage, destRect, srcRect, GraphicsUnit.Pixel);
startY = Convert.ToInt32(startY + b - scale);
e.HasMorePages = (startY < pageImage.Height);
}
could you please make it works correctly.
you can download the source code from (here).
thanks in advanced.
I tried to complete your task.
Here you go. Hope it helps.
This method prints the image on several pages (or one if image is small).
private void printImage_Btn_Click(object sender, EventArgs e)
{
list = new List<Image>();
Graphics g = Graphics.FromImage(image_PctrBx.Image);
Brush redBrush = new SolidBrush(Color.Red);
Pen pen = new Pen(redBrush, 3);
decimal xdivider = image_PctrBx.Image.Width / 595m;
int xdiv = Convert.ToInt32(Math.Ceiling(xdivider));
decimal ydivider = image_PctrBx.Image.Height / 841m;
int ydiv = Convert.ToInt32(Math.Ceiling(ydivider));
/*int xdiv = image_PctrBx.Image.Width / 595; //This is the xsize in pt (A4)
int ydiv = image_PctrBx.Image.Height / 841; //This is the ysize in pt (A4)
// # 72 dots-per-inch - taken from Adobe Illustrator
if (xdiv >= 1 && ydiv >= 1)
{*/
for (int i = 0; i < xdiv; i++)
{
for (int y = 0; y < ydiv; y++)
{
Rectangle r;
try
{
r = new Rectangle(i * Convert.ToInt32(image_PctrBx.Image.Width / xdiv),
y * Convert.ToInt32(image_PctrBx.Image.Height / ydiv),
image_PctrBx.Image.Width / xdiv,
image_PctrBx.Image.Height / ydiv);
}
catch (Exception)
{
r = new Rectangle(i * Convert.ToInt32(image_PctrBx.Image.Width / xdiv),
y * Convert.ToInt32(image_PctrBx.Image.Height),
image_PctrBx.Image.Width / xdiv,
image_PctrBx.Image.Height);
}
g.DrawRectangle(pen, r);
list.Add(cropImage(image_PctrBx.Image, r));
}
}
g.Dispose();
image_PctrBx.Invalidate();
image_PctrBx.Image = list[0];
PrintDocument printDocument = new PrintDocument();
printDocument.PrintPage += PrintDocument_PrintPage;
PrintPreviewDialog previewDialog = new PrintPreviewDialog();
previewDialog.Document = printDocument;
pageIndex = 0;
previewDialog.ShowDialog();
// don't forget to detach the event handler when you are done
printDocument.PrintPage -= PrintDocument_PrintPage;
}
This method prints every picture in the List in the needed dimensions (A4 size):
private void PrintDocument_PrintPage(object sender, PrintPageEventArgs e)
{
// Draw the image for the current page index
e.Graphics.DrawImageUnscaled(list[pageIndex],
e.PageBounds.X,
e.PageBounds.Y);
// increment page index
pageIndex++;
// indicate whether there are more pages or not
e.HasMorePages = (pageIndex < list.Count);
}
This method crops the image and returns every part of the image:
private static Image cropImage(Image img, Rectangle cropArea)
{
Bitmap bmpImage = new Bitmap(img);
Bitmap bmpCrop = bmpImage.Clone(cropArea, System.Drawing.Imaging.PixelFormat.DontCare);
return (Image)(bmpCrop);
}
The Image gets loaded from the PictureBox, so make sure the image is loaded. (No exception handling yet).
internal string tempPath { get; set; }
private int pageIndex = 0;
internal List<Image> list { get; set; }
These variables are defined as global variables.
You can download a sample project here:
http://www.abouchleih.de/projects/PrintImage_multiplePages.zip // OLD Version
http://www.abouchleih.de/projects/PrintImage_multiplePages_v2.zip // NEW
I have Created a Class file for multiple page print a single large image.
Cls_PanelPrinting.Print Print =new Cls_PanelPrinting.Print(PnlContent/Image);
You have to Pass the panel or image.
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;
using System.IO;
using System.Drawing.Printing;
namespace Cls_PanelPrinting
{
public class Print
{
readonly PrintDocument printdoc1 = new PrintDocument();
readonly PrintPreviewDialog previewdlg = new PrintPreviewDialog();
public int page = 1;
internal string tempPath { get; set; }
private int pageIndex = 0;
internal List<Image> list { get; set; }
private int _Line = 0;
private readonly Panel panel_;
public Print(Panel pnl)
{
panel_ = pnl;
printdoc1.PrintPage += (printdoc1_PrintPage);
PrintDoc();
}
private void printdoc1_PrintPage(object sender, PrintPageEventArgs e)
{
Font myFont = new Font("Cambria", 10, FontStyle.Italic, GraphicsUnit.Point);
float lineHeight = myFont.GetHeight(e.Graphics) + 4;
float yLineTop = 1000;
int x = e.MarginBounds.Left;
int y = 25; //e.MarginBounds.Top;
e.Graphics.DrawImageUnscaled(list[pageIndex],
x,y);
pageIndex++;
e.HasMorePages = (pageIndex < list.Count);
e.Graphics.DrawString("Page No: " + pageIndex, myFont, Brushes.Black,
new PointF(e.MarginBounds.Right, yLineTop));
}
public void PrintDoc()
{
try
{
Panel grd = panel_;
Bitmap bmp = new Bitmap(grd.Width, grd.Height, grd.CreateGraphics());
grd.DrawToBitmap(bmp, new Rectangle(0, 0, grd.Width, grd.Height));
Image objImage = (Image)bmp;
Bitmap objBitmap = new Bitmap(objImage, new Size(700, objImage.Height));
Image PrintImage = (Image)objBitmap;
list = new List<Image>();
Graphics g = Graphics.FromImage(PrintImage);
Brush redBrush = new SolidBrush(Color.Red);
Pen pen = new Pen(redBrush, 3);
decimal xdivider = panel_.Width / 595m;
// int xdiv = Convert.ToInt32(Math.Ceiling(xdivider));
decimal ydivider = panel_.Height / 900m;
int ydiv = Convert.ToInt32(Math.Ceiling(ydivider));
int xdiv = panel_.Width / 595; //This is the xsize in pt (A4)
for (int i = 0; i < xdiv; i++)
{
for (int y = 0; y < ydiv; y++)
{
Rectangle r;
if (panel_.Height > 900)
{
try
{
if (list.Count > 0)
{
r = new Rectangle(0, (900 * list.Count), PrintImage.Width, PrintImage.Height - (900 * list.Count));
}
else
{
r = new Rectangle(0, 0, PrintImage.Width, 900);
}
list.Add(cropImage(PrintImage, r));
}
catch (Exception)
{
list.Add(PrintImage);
}
}
else { list.Add(PrintImage); }
}
}
g.Dispose();
PrintImage = list[0];
PrintDocument printDocument = new PrintDocument();
printDocument.PrintPage += printdoc1_PrintPage;
PrintPreviewDialog previewDialog = new PrintPreviewDialog();
previewDialog.Document = printDocument;
pageIndex = 0;
printDocument.DefaultPageSettings.PrinterSettings.PrintToFile = true;
string path = "d:\\BillIng.xps";
if (File.Exists(path))
File.Delete(path);
printDocument.DefaultPageSettings.PrinterSettings.PrintFileName = "d:\\BillIng.xps";
printDocument.PrintController = new StandardPrintController();
printDocument.Print();
printDocument.PrintPage -= printdoc1_PrintPage;
}
catch { }
}
private static Image cropImage(Image img, Rectangle cropArea)
{
Bitmap bmpImage = new Bitmap(img);
Bitmap bmpCrop = bmpImage.Clone(cropArea, System.Drawing.Imaging.PixelFormat.DontCare);
return (Image)(bmpCrop);
}
}
}

Categories