I have a Panel that has exactly 4 picture boxes, and labels inside. I want to print all the contents inside the Panel but it is only showing the two picture boxes - in the preview.
I have this:
But it is only showing this (when I click the print button):
Here is my code for printing:
private void BtnPrint_Click(object sender, EventArgs e)
{
Print(this.pnlID);
}
public void Print(Panel pnl)
{
PrinterSettings ps = new PrinterSettings();
pnlID = pnl;
GetPrintArea(pnl);
prntprvw.Document = printdoc;
printdoc.PrintPage += new PrintPageEventHandler(printdoc_printpage);
prntprvw.ShowDialog();
}
public void printdoc_printpage(Object sender, PrintPageEventArgs e)
{
Rectangle pagearea = e.PageBounds;
e.Graphics.DrawImage(MemoryImage, (pagearea.Width / 2) - (this.pnlID.Width / 2), this.pnlID.Location.Y);
}
Bitmap MemoryImage;
public void GetPrintArea(Panel pnl)
{
MemoryImage = new Bitmap(pnl.Width, pnl.Height);
//Rectangle rect = new Rectangle(0, 0, pnl.Width, pnl.Height);
pnl.DrawToBitmap(MemoryImage, new Rectangle(0, 0, pnl.Width, pnl.Height));
}
How can I print all the contents inside the panel?
Related
The code below is showing me half part of the group box in print preview:
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) {
// Bitmap bmp = new Bitmap(groupBox1.ClientRectangle.Width, groupBox1.ClientRectangle.Height);
// groupBox1.DrawToBitmap(bmp, groupBox1.ClientRectangle);
// e.Graphics.DrawImage(bmp, 0, 0);
Bitmap bmp = new Bitmap(groupBox1.Width, groupBox1.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
groupBox1.DrawToBitmap(bmp, new Rectangle(0, 0, groupBox1.Width, groupBox1.Height));
e.Graphics.DrawImage((Image) bmp, 0, 0);
}
private void button1_Click(object sender, EventArgs e) {
PrintPreviewDialog ppd = new PrintPreviewDialog();
PrintDocument Pd = new PrintDocument();
Pd.PrintPage += this.printDocument1_PrintPage;
ppd.Document = Pd;
ppd.ShowDialog();
}
You need to draw within the bounds of the page.
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
var g = e.Graphics;
var srcRect = new Rectangle(0, 0, groupBox1.Width, groupBox1.Height);
var desRect = new Rectangle(e.PageBounds.X, e.PageBounds.Y, e.PageBounds.Width, srcRect.Height);
//Or to draw within the margin
//var desRect = new Rectangle(e.MarginBounds.X, e.MarginBounds.Y, e.MarginBounds.Width, srcRect.Height);
using (var bmp = new Bitmap(srcRect.Width, srcRect.Height))
{
groupBox1.DrawToBitmap(bmp, srcRect);
g.DrawImage(bmp, desRect, srcRect, GraphicsUnit.Pixel);
}
}
Also, create the PrintDocument object and register its PrintPage event in the Form's constructor or Load event to avoid repeating that again and again in the button1_Click event. And don't forget to dispose the disposable objects.
I have a panel on a tabcontrolpanel that takes up roughly 35% of the screen. I am printing the panel, and it prints the exact size it is on the screen. Is it possible in C# and winforms to scale the image to print on a 8.5x11 peice of paper (even if I have to print it landscape)?
This is my current code --
private void btnPrint_Click(object sender, EventArgs e)
{
PrintDocument doc = new PrintDocument();
doc.PrintPage += new SPrintPageEventHandler(doc_PrintPage);
doc.Print();
}
private void doc_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
Bitmap image = new Bitmap(panelToPrint.Width, panelToPrint.Height, panelToPrint.CreateGraphics());
panelToPrint.DrawToBitmap(image, new Rectangle(0, 0, panelToPrint.Width, panelToPrint.Height));
RectangleF bounds = e.PageSettings.PrintableArea;
float factor = ((float)image.Height / (float)image.Width);
e.Graphics.DrawImage(image, bounds.Left, bounds.Top, bounds.Width, factor * bounds.Width);
}
Edit
I tried to modify my syntax to by default print in landscape mode, but I am still getting the same output as before, just the image printing roughly on the top 15% of the page
private void btnPrint_Click(object sender, EventArgs e)
{
System.Drawing.Printing.PrintDocument doc = new System.Drawing.Printing.PrintDocument();
doc.DefaultPageSettings.Landscape = true;
PrintDialog pdi = new PrintDialog();
pdi.Document = doc;
if (pdi.ShowDialog() == DialogResult.OK)
{
doc.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(doc_PrintPage);
doc.Print();
}
else
{
MessageBox.Show("User cancelled the print job");
}
}
private void doc_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
Bitmap image = new Bitmap(panelToPrint.Width, panelToPrint.Height, panelToPrint.CreateGraphics());
panelToPrint.DrawToBitmap(image, new Rectangle(0, 0, panelToPrint.Width, panelToPrint.Height));
RectangleF bounds = e.PageSettings.PrintableArea;
float factor = ((float)image.Height / (float)image.Width);
e.Graphics.DrawImage(image, bounds.Left, bounds.Top, bounds.Width, factor * bounds.Width);
}
control.DrawToBitmap does exactly that. It prints the control (as you see it on the screen) to a bitmap. If you want to print it in a different size you have to resize the panel before printing.
A better approach is to draw your data that is contained into the panel directly to the page using graphics methods like DrawString etc.
I have a panel with multiple picturebox created at runtime.
The user will create a rectangle on any picture box and the selected part will be displayed on a preview picturebox.
I have successfully done the above using the below code.
Question
I want to clear the selection rectangle at mouseup event. Used invalidate but not working.
From how to clear the graphics(rectangle shape) in picturebox
Also, when I scroll the panel the same rectangle(mouse selection) is shown on all picturebox.
private void Picture_Paint(object sender, PaintEventArgs e)
{
if (Rect!=null && Rect.Width>0 && Rect.Height>0)
{
e.Graphics.FillRectangle(selectionBrush, Rect);
}
}
private void Picture_MouseDown(object sender, MouseEventArgs e)
{
RecStartpoint = e.Location;
((PictureBox)sender).Invalidate();
}
private void Picture_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
Point tempEndPoint = e.Location;
Rect.Location = new Point(
Math.Min(RecStartpoint.X, tempEndPoint.X),
Math.Min(RecStartpoint.Y, tempEndPoint.Y));
Rect.Size = new Size(
Math.Abs(RecStartpoint.X - tempEndPoint.X),
Math.Abs(RecStartpoint.Y - tempEndPoint.Y));
((PictureBox)sender).Invalidate();
}
private void Picture_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
PictureBox org_pic = (PictureBox)(sender);
Point RecEndpoint=e.Location;
int xDown = Math.Min(RecStartpoint.X,RecEndpoint.X);
int yDown = Math.Min(RecStartpoint.Y, RecEndpoint.Y);
int xUp = Math.Max(RecStartpoint.X,RecEndpoint.X);
int yUp = Math.Max(RecStartpoint.Y,RecEndpoint.Y);
Rectangle rec = new Rectangle(xDown, yDown, Math.Abs(xUp - xDown), Math.Abs(yUp - yDown));
xDown = xDown * org_pic.Image.Width / org_pic.Width;
yDown = yDown * org_pic.Image.Height / org_pic.Height;
xUp = xUp * org_pic.Image.Width / org_pic.Width;
yUp = yUp * org_pic.Image.Height / org_pic.Height;
rectCropArea = new Rectangle(xDown, yDown, Math.Abs(xUp - xDown), Math.Abs(yUp - yDown));
pictureBox_preview_photo.Refresh();
Bitmap sourceBitmap = new Bitmap(org_pic.ImageLocation);
Graphics g = pictureBox_preview_photo.CreateGraphics();
g.DrawImage(sourceBitmap, new Rectangle(0, 0, pictureBox_preview_photo.Width, pictureBox_preview_photo.Height), rectCropArea, GraphicsUnit.Pixel);
}
I would try this approach:
First, make Image variable, in the scope of form
public partial class Form1 : Form
{
//variable for holding original image, before rectangle is drawn on it
Image originalImage = null;
public Form1()
{
InitializeComponent();
}
//rest of form's code...
second, save current picture in that variable on MouseDown
private void Picture_MouseDown(object sender, MouseEventArgs e)
{
//save it
startImage = ((PictureBox)sender).Image;
RecStartpoint = e.Location;
((PictureBox)sender).Invalidate();
}
lastly, on the end of MouseUp event, set Rectangle's width and height to zero and restore saved, original image
//snipped code
pictureBox_preview_photo.Refresh();
Bitmap sourceBitmap = new Bitmap(org_pic.ImageLocation);
Graphics g = pictureBox_preview_photo.CreateGraphics();
g.DrawImage(sourceBitmap, new Rectangle(0, 0, pictureBox_preview_photo.Width, pictureBox_preview_photo.Height), rectCropArea, GraphicsUnit.Pixel);
//make rectangle's widht and height 0 so that Paint event won't draw it
Rect.Width = Rect.Height = 0;
//restore image
this.Picture.Image = startImage;
I didn't understand that second question.
I am using BufferedGraphics to redraw my form. I wish to redraw the form's controls all by myself, so I can draw lines wherever I want while I can still use the Form Designer to align my controls.
I've tried SuspendLayout but it make no use here.
Code:
using System;
using System.Drawing;
using System.Windows.Forms;
public partial class Form1 : Form
{
BufferedGraphicsContext context;
BufferedGraphics grafx;
PictureBox pic1, pic2;
public Form1()
{
SetStyle((ControlStyles)(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint), true);
InitializeComponent();
//Add picturebox
pic1 = new PictureBox();
pic1.BackColor = Color.Black;
pic1.SetBounds(50, 50, 100, 50);
Controls.Add(pic1);
pic2 = new PictureBox();
pic2.BackColor = Color.Gray;
pic2.SetBounds(75, 50, 50, 100);
Controls.Add(pic2);
}
private void Form1_Load(object sender, EventArgs e)
{
context = BufferedGraphicsManager.Current;
context.MaximumBuffer = new Size(Width, Height);
grafx = context.Allocate(CreateGraphics(), new Rectangle(0, 0, Width, Height));
}
public override void Refresh() { }
protected override void OnPaintBackground(PaintEventArgs e) { }
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = grafx.Graphics;
g.Clear(BackColor);
Bitmap bmp = new Bitmap(Width, Height);
foreach (Control c in Controls)
c.DrawToBitmap(bmp, new Rectangle(c.Left, c.Top, c.Width, c.Height));
g.DrawImage(bmp, 0, 0);
g.DrawLine(new Pen(Color.Red, 4), 0, 0, ClientSize.Width, ClientSize.Height);
grafx.Render(Graphics.FromHwnd(Handle));
}
private void Form1_Resize(object sender, EventArgs e)
{
context.MaximumBuffer = new Size(this.Width, this.Height);
if (grafx != null)
{
grafx.Dispose();
grafx = null;
}
grafx = context.Allocate(this.CreateGraphics(), new Rectangle(0, 0, Width, Height));
base.Refresh();
}
}
I need the line to be drawn at the top of the controls (picturebox), but the code turns out to be drawn below the controls.
I'm trying to print a panel that has pictureboxes, labels and textboxes. I want to print it on A4 paper so the panel has 595x842.
I have tried:
private void print_Click(object sender, EventArgs e)
{
PrintPanel(panel1);
}
private void PrintPanel(Panel pnl)
{
PrintDialog myPrintDialog = new PrintDialog();
System.Drawing.Bitmap memoryImage = new System.Drawing.Bitmap(pnl.Width, pnl.Height);
pnl.DrawToBitmap(memoryImage, pnl.ClientRectangle);
if (myPrintDialog.ShowDialog() == DialogResult.OK)
{
System.Drawing.Printing.PrinterSettings values;
values = myPrintDialog.PrinterSettings;
myPrintDialog.Document = printDocument1;
printDocument1.PrintController = new StandardPrintController();
printDocument1.Print();
}
printDocument1.Dispose();
}
When I try to print it I go to the One Note and all I get is a white page. What seems to be the problem?
I modified the code a bit. Now I get some output but it's still not good...
This is the code I used:
private void print_Click(object sender, EventArgs e)
{
System.Drawing.Printing.PrintDocument doc = new System.Drawing.Printing.PrintDocument();
doc.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(doc_PrintPage);
doc.Print();
}
private void doc_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
Panel grd = new Panel();
Bitmap bmp = new Bitmap(grd.Width, grd.Height, grd.CreateGraphics());
grd.DrawToBitmap(bmp, new Rectangle(0, 0, grd.Width, grd.Height));
RectangleF bounds = e.PageSettings.PrintableArea;
float factor = ((float)bmp.Height / (float)bmp.Width);
e.Graphics.DrawImage(bmp, bounds.Left, bounds.Top, bounds.Width, factor * bounds.Width);
}
And I get this:
http://i.stack.imgur.com/HB1EH.png
Can someone help?
You are printing the wrong panel. Your code is creating a new empty panel and trying to print that (which it successfully does). You need to reference the existing panel you want to print:
void doc_PrintPage(object sender, PrintPageEventArgs e) {
using (Bitmap bmp = new Bitmap(panel1.ClientSize.Width, panel1.ClientSize.Height)) {
panel1.DrawToBitmap(bmp, panel1.ClientRectangle);
RectangleF bounds = e.PageSettings.PrintableArea;
float factor = ((float)bmp.Height / (float)bmp.Width);
e.Graphics.DrawImage(bmp, bounds.Left, bounds.Top,
bounds.Width, factor * bounds.Width);
}
}