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...
Related
I'm generating a barcode depending on how many inputs that the user set in the numericUpDown control. The problem is when generating a lot of barcodes, the other barcodes cannot be seen in the printpreviewdialog because it I cannot apply a nextline or \n every 4-5 Images.
int x = 0, y = 10;
for (int i = 1; i <= int.Parse(txtCount.Text); i++)
{
idcount++;
connection.Close();
Zen.Barcode.Code128BarcodeDraw barcode = Zen.Barcode.BarcodeDrawFactory.Code128WithChecksum;
Random random = new Random();
string randomtext = "MLQ-";
int j;
for (j = 1; j <= 6; j++)
{
randomtext += random.Next(0, 9).ToString();
Image barcodeimg = barcode.Draw(randomtext, 50);
resultimage = new Bitmap(barcodeimg.Width, barcodeimg.Height + 20);
using (var graphics = Graphics.FromImage(resultimage))
using (var font = new Font("Arial", 11)) // Any font you want
using (var brush = new SolidBrush(Color.Black))
using (var format = new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Far}) // Also, horizontally centered text, as in your example of the expected output
{
graphics.Clear(Color.White);
graphics.DrawImage(barcodeimg, 0, 0);
graphics.DrawString(randomtext, font, brush, resultimage.Width / 2, resultimage.Height, format);
}
x += 25;
}
e.Graphics.DrawImage(resultimage, x, y);
}
There's no "new lines" in rasterized graphics. There's pixels. You've got the right idea, every n number of images, add a new line. But since you're working with pixels, let's say every 4 images you're going to need to add a vertical offset by modifying the y coordinate of all your graphics draw calls. This offset, combined with a row height in pixels could look something like this:
var rowHeight = 250; // pixels
var maxColumns = 4;
var verticalOffset = (i % maxColums) * rowHeight;
Then, when you can supply a y coordinate, starting at or near 0, add the vertical offset to it.
I need to develop a chart using datavisualization. Now the chart looks like
below
In the above chart i am using rangebar to show min and max values, in rangebar the label (65---210) now comes in the middle part. But i need to show the min and max like one in red. ie min value in the start position of the rangebar and max value in the end position of the rangebar.
Please let me know if there is any way to do it
The way to do it is by handling the chart's Paint event.
You would need to do some more sophisticated calculations using the Graphics object to make it work for the generic case. But it should get you started.
public partial class WebForm1 : System.Web.UI.Page
{
float deltax, deltay, deltay2;
Font font;
Brush brush;
Random r;
protected void Page_Load(object sender, EventArgs e)
{
deltax = 7.5F;
deltay = 60;
deltay2 = 5;
font = new Font("Courier", 14);
brush = new SolidBrush(Color.Red);
r = new Random();
for (int i = 1; i <= 5; i++)
Chart1.Series[0].Points.Add(new DataPoint(i, new double[2] { r.Next(10, 40), r.Next(60, 90) }));
}
protected void Chart1_PostPaint(object sender, ChartPaintEventArgs e)
{
if (e.ChartElement.ToString().Contains("Series"))
{
int count = Chart1.Series[0].Points.Count - 1;
for (int i = count; i >= 0; i--)
{
DataPoint dp = Chart1.Series[0].Points[i];
float size = (float)(deltax*(dp.YValues[1] - dp.YValues[0] + deltay2));
float x = (float)(deltax * dp.YValues[0]);
float y = (float)(deltay * (count - dp.XValue + 2));
e.ChartGraphics.Graphics.DrawString(string.Format("{0}", dp.YValues[0]), font, brush, new PointF(x, y));
e.ChartGraphics.Graphics.DrawString(string.Format("{0}", dp.YValues[1]), font, brush, new PointF(x + size, y));
}
}
}
}
I am now drawing to a panel some dots to indicate a sort of dotted grid with 1% of margin of total panel width.
This is what I am doing now:
private void panel1_Paint(object sender, PaintEventArgs e)
{
Pen my_pen = new Pen(Color.Gray);
int x,y;
int k = 1 ,t = 1;
int onePercentWidth = panel1.Width / 100;
for (y = onePercentWidth; y < panel1.Height-1; y += onePercentWidth)
{
for (x = onePercentWidth; x < panel1.Width-1; x += onePercentWidth)
{
e.Graphics.DrawEllipse(my_pen, x, y, 1, 1);
}
}
}
What is bothering me is that when the app starts I can see the dots being drawn on the panel. Even if it is very quick it still bothers me a lot.
Is it possible to draw the dots on the panel and load it directly drawn?
Thank you for the help
You could create a bitmap and draw it instead.
But before you do that: DrawEllipse is a little expensive. Use DrawLine with a Pen that has a dotted linestyle instead:
int onePercentWidth = panel1.ClientSize.Width / 100;
using (Pen my_pen = new Pen(Color.Gray, 1f))
{
my_pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom;
my_pen.DashPattern = new float[] { 1F, onePercentWidth -1 };
for (int y = onePercentWidth; y < panel1.ClientSize.Height - 1; y += onePercentWidth)
e.Graphics.DrawLine(my_pen, 0, y, panel1.ClientSize.Width, y);
}
Note that I am using using so I don't leak the Pen and ClientSize so I use only the inner width. Also note the exaplanation about the custom DashPattern on MSDN
I want to print two images on single page.
I have tried below code, but it is printing all images on different pages.
public void PD_PrintPage(object sender, PrintPageEventArgs e)
{
float W = e.MarginBounds.Width;
float H = e.MarginBounds.Height;
for (; FileCounter >= 0; FileCounter--)
{
try
{
Bitmap Bmp = new Bitmap(BmpFiles[FileCounter]);
if (Bmp.Width / W < Bmp.Height / H)
W = Bmp.Width * H / Bmp.Height;
else
H = Bmp.Height * W / Bmp.Width;
e.Graphics.DrawImage(Bmp, 0, 0, W, H);
break;
}
catch
{
}
}
FileCounter -= 1;
if (FileCounter > 0)
{
e.HasMorePages = true;
}
else
{
FileCounter = BmpFiles.Length - 1;
}
}
this will print all images in different page
I want some functionality that will print one image ,leave some space and again prine other image in same page if space is remaining.
In your code you're printig just one image per page because you leave the loop with the break-statement at the end of try. Instead of using break without a condition you should leave the loop dynamically based on the decision if it is possible to print only one image (not nough space for second image) ore two images (you achieved what you wanted).
//for-loop for printing maximum two images as long as there are files to print
for (int i = 0; i < 2 && FileCounter >= 0; i++)
{
//here comes your printing code just indicated with the draw-call
e.Graphics.DrawImage(Bmp, 0, 0, W, H);
//after a image was printed decrement your filecounter
FileCounter --;
//after a image was drawn check if there is enough space for the next image
//if there is not enough space leave the loop with break
if(condition)
break;
}
At the moment I don't have enough reputation for commenting something on this page... so: never use 'goto' as "Sayka" proposes in his answer. That is really bad style & coding
The working of printDocument is like this:
First the program reaches the printPage function, reads all the code and at the end of the function, if there exists a line e.hasMorePages = true; , then the program re-enters the function from the begining and read again the codes to print it to the next page and continues until it reads a line e.hasMorepages = false .. So u dont have to put a loop inside the function. What you have to do is to make variables inside the class, and incre or decrement the variables to make a condition that satisfies e.hasMorePages = false after your printing job has finished..
public void PD_PrintPage(object sender, PrintPageEventArgs e)
{
float W = e.MarginBounds.Width;
// if you are calculating the whole page margin, then split it to carry 2 images
float H = e.MarginBounds.Height / 2;
// for space btwn images
H -= 5.0;
// First Image
try
{
Bitmap Bmp = new Bitmap(BmpFiles[FileCounter]);
if (Bmp.Width / W < Bmp.Height / H)
W = Bmp.Width * H / Bmp.Height;
else
H = Bmp.Height * W / Bmp.Width;
e.Graphics.DrawImage(Bmp, 0, 0, W, H);
break;
}
catch
{
}
FileCounter --;
if (FileCounter < 0) goto goDaddy;
//Second Img
try
{
Bitmap Bmp = new Bitmap(BmpFiles[FileCounter]);
if (Bmp.Width / W < Bmp.Height / H)
W = Bmp.Width * H / Bmp.Height;
else
H = Bmp.Height * W / Bmp.Width;
e.Graphics.DrawImage(Bmp, 0, H + 2.5, W, H);
break;
}
catch
{
}
FileCounter --;
goDaddy:;
e.HasMorePages = (FileCounter >= 0)
}
I haven't checked the code but just tryin to show you the concept..
I found this to work extremely well, doesn't lose any image quality I experienced using memory streams.
private void printBothGraphs_Click(object sender, EventArgs e)
{
PrintPreviewDialog custom = new PrintPreviewDialog();
custom.ClientSize = new Size(1000, 750);
System.Drawing.Printing.PrintDocument pd = new System.Drawing.Printing.PrintDocument();
pd.DefaultPageSettings.Color = true;
pd.PrintPage += new PrintPageEventHandler(pd_PrintPageBoth);
custom.Document = pd;
custom.ShowDialog();
}
private void pd_PrintPageBoth(object sender, PrintPageEventArgs ev)
{
// Create and initialize print font
System.Drawing.Font printFont = new System.Drawing.Font("Arial", 10);
ev.PageSettings.Color = true;
// Create Rectangle structure, used to set the position of the chart Rectangle
Rectangle myRec = new System.Drawing.Rectangle(ev.MarginBounds.X, ev.MarginBounds.Y, ev.MarginBounds.Width, ev.MarginBounds.Height / 2);
Rectangle myRec2 = new System.Drawing.Rectangle(ev.MarginBounds.X, ev.MarginBounds.Height / 2 + 90, ev.MarginBounds.Width, ev.MarginBounds.Height / 2);
//dataChart and outputGraph are two mscharts in my form
dataChart.Printing.PrintPaint(ev.Graphics, myRec);
outputGraph.Printing.PrintPaint(ev.Graphics, myRec2);
}
I've looked all over for something to help me with this, but so far nothing. I am trying to create a program that allows a user to print a collection of pdfs. I am using ABCPDF9 to get my pdfs (most of which are stored as html) and append them all to a single ABCPDF.Doc object. The problem I'm getting is when I have these multiple pages I end up with only one page of the pdf printing. Here are some code snippets below.
private void ProcessAndPrintSelected()
{
var selectedForm = SubSonicRepository.Instance.CommunicationRepository.GetMessageTemplateByID((int)cmboChooseForm.SelectedValue);
_currentItemIndex = 0;
int itemsCount = dataGridViewLoans.RowCount;
_currentPrintPageIndex = 1;
foreach (DataGridViewRow row in this.dataGridViewLoans.Rows)
{
lblPrinterProgress.Text = "Printing document " + _currentItemIndex + " of " + itemsCount + ".";
lblPrinterProgress.Refresh();
Application.DoEvents();
BulkPrinterLoanModel loan = row.DataBoundItem as BulkPrinterLoanModel;
try
{
if (selectedForm.MailMessageContent != null)
{
byte[] formBytes = GetFormBytes(selectedForm.ID, loan.ApplicantID, loan.LoanID);
doc.Read(formBytes);
appendedDocs.Append(doc);
}
else
{
throw new InvalidOperationException("No PDF data to print.");
}
}
catch (Exception x)
{
//for now, don't do anything, not even logging, but don't halt queue either.
MessageBox.Show(x.ToString());
}
}
printDoc.PrintPage += new PrintPageEventHandler(pd_PrintPage);
printDoc.PrinterSettings.FromPage = 1;
printDoc.PrinterSettings.ToPage = appendedDocs.PageCount;
printDoc.PrinterSettings.MinimumPage = 1;
printDoc.PrinterSettings.MaximumPage = appendedDocs.PageCount;
PrintDialog pDialog = new PrintDialog();
pDialog.Document = printDoc;
pDialog.AllowSomePages = true;
if (pDialog.ShowDialog() == DialogResult.OK)
{
pDialog.Document.Print();
}
}
and my printpage event.
void pd_PrintPage(object sender, PrintPageEventArgs e)
{
XRect cropBox = appendedDocs.CropBox;
double srcWidth = (cropBox.Width / 72) * 100;
double srcHeight = (cropBox.Height / 72) * 100;
double pageWidth = e.PageBounds.Width;
double pageHeight = e.PageBounds.Height;
double marginX = e.PageSettings.HardMarginX;
double marginY = e.PageSettings.HardMarginY;
//center it
double x = (pageWidth - srcWidth) / 2;
double y = (pageHeight - srcHeight) / 2;
x -= marginX;
y -= marginY;
RectangleF rect = new RectangleF((float)x, (float)y, (float)srcWidth, (float)srcHeight);
appendedDocs.Rect.SetRect(cropBox);
int rez = e.PageSettings.PrinterResolution.X;
appendedDocs.Rendering.DotsPerInch = rez;
Graphics g = e.Graphics;
using (Bitmap bitmap = appendedDocs.Rendering.GetBitmap())
{
g.DrawImage(bitmap, rect);
}
}
I've looked in the ABCPDF manual, but all the help on printing is presented in their sample project which I'm having a hard time understanding. Any help on this matter would be appreciated. Thanks :)
I got it, mostly from looking at the following question. I needed to use the Doc.PageNumber to access each page of the pdf. Here's the print page event where I changed the code.
void pd_PrintPage(object sender, PrintPageEventArgs e)
{
_currentItemIndex++;//added index to keep track of page. default to 1
appendedDocs.PageNumber = _currentItemIndex;//set to current page for printing
XRect cropBox = appendedDocs.CropBox;
double srcWidth = (cropBox.Width / 72) * 100;
double srcHeight = (cropBox.Height / 72) * 100;
double pageWidth = e.PageBounds.Width;
double pageHeight = e.PageBounds.Height;
double marginX = e.PageSettings.HardMarginX;
double marginY = e.PageSettings.HardMarginY;
//center it
double x = (pageWidth - srcWidth) / 2;
double y = (pageHeight - srcHeight) / 2;
x -= marginX;
y -= marginY;
RectangleF rect = new RectangleF((float)x, (float)y, (float)srcWidth, (float)srcHeight);
appendedDocs.Rect.SetRect(cropBox);
int rez = e.PageSettings.PrinterResolution.X;
appendedDocs.Rendering.DotsPerInch = rez;
Graphics g = e.Graphics;
using (Bitmap bitmap = appendedDocs.Rendering.GetBitmap())
{
g.DrawImage(bitmap, rect);
}
e.HasMorePages = _currentItemIndex < appendedDocs.PageCount;//check for more pages.
}
Feel silly having asked this question and then answering myself. But it feels good knowing that this question is now out there for anyone else that gets stuck on the issue.