I'm pretty new to C# but I finally have my first program up and running and I need to make it print. Its a window form with information and calculations on different tab controls, somewhat like Excel. The page that is currently being looked at prints fine with the copyfromscreen method, but I cannot get additional pages to print correctly. I have about 20 tabs I would like to be able to print at one time. I found a way to print the contents of controls into a textfile, but I would much prefer to be able to print what the form looks like. Thanks.
Bitmap memoryImage;
Bitmap memoryImage2;
private void CaptureScreen()
{
Graphics myGraphics = this.CreateGraphics();
Size s = tabControlMain.Size;
s.Width = s.Width + 20;
memoryImage = new Bitmap(s.Width, s.Height, myGraphics);
Graphics memoryGraphics = Graphics.FromImage(memoryImage);
memoryGraphics.CopyFromScreen(this.Location.X+15, this.Location.Y+80, 0, 0, s);
tabControlMain.SelectedIndex = 1;
memoryImage2 = new Bitmap(s.Width, s.Height, myGraphics);
Graphics memoryGraphics2 = Graphics.FromImage(memoryImage2);
memoryGraphics2.CopyFromScreen(this.Location.X + 15, this.Location.Y + 80, 0, 0, s);
}
private void printDocumentReal_PrintPage(System.Object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
e.Graphics.DrawImage(memoryImage, 0, 0);
e.Graphics.DrawImage(memoryImage2, 0, 550);
}
private void printToolStripButton_Click(object sender, EventArgs e)
{
CaptureScreen();
printDocumentReal.Print();
}
First, you should use PrintDocument and PrintPreviewDialog objects for print related tasks and an event handler for printing.
Second, you need to preform some optimization for your code, here's the solution:
private void printToolStripButton_Click(object sender, EventArgs e)
{
PrintDocument document = new PrintDocument();
document.PrintPage += new PrintPageEventHandler(document_PrintPage);
PrintPreviewDialog preview = new PrintPreviewDialog() { Document = document };
// you will be able to preview all pages before print it ;)
try
{
preview.ShowDialog();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + "\nYou need to install a printer to preform print-related tasks!", "Print Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Boolean firstPage = true;
private void document_PrintPage(object sender, PrintPageEventArgs e)
{
if (firstPage)
{
tabControlMain.SelectTab(0);
firstPage = false;
}
Graphics g = e.Graphics;
TabPage tab = tabControlMain.SelectedTab;
using (Bitmap img = new Bitmap(tab.Width, tab.Height))
{
tab.DrawToBitmap(img, tab.ClientRectangle);
g.DrawImage(img, new Point(e.MarginBounds.X, e.MarginBounds.Y)); // MarginBounds means the margins of the page
}
if (tabControlMain.SelectedIndex + 1 < tabControlMain.TabCount)
{
tabControlMain.SelectedIndex++;
e.HasMorePages = true;//If you set e.HasMorePages to true, the Document object will call this event handler again to print the next page.
}
else
{
e.HasMorePages = false;
firstPage = true;
}
}
I hope it's working fine with you And here's an additional one if you need to save all tabs as set of images on your hard disk:
public void RenderAllTabs()
{
foreach (TabPage tab in tabControlMain.TabPages)
{
tabControlMain.SelectTab(tab);
using (Bitmap img = new Bitmap(tab.Width, tab.Height))
{
tab.DrawToBitmap(img, tab.ClientRectangle);
img.Save(string.Format(#"C:\Tabs\{0}.png", tab.Text));
}
}
}
Try using DrawToBitmap method of TabPage instead:
private void CaptureScreen()
{
memoryImage = new Bitmap(tabControlMain.SelectedTab.Width, tabControlMain.SelectedTab.Height);
tabControlMain.SelectedTab.DrawToBitmap(memoryImage, tabControlMain.SelectedTab.ClientRectangle);
tabControlMain.SelectedIndex = 1;
memoryImage2 = new Bitmap(tabControlMain.SelectedTab.Width, tabControlMain.SelectedTab.Height);
tabControlMain.SelectedTab.DrawToBitmap(memoryImage2, tabControlMain.SelectedTab.ClientRectangle);
}
To get all the images of your TabPages, you can make a loop like this:
List<Bitmap> images = new List<Bitmap>();
private void CaptureScreen(){
foreach(TabPage page in tabControlMain.TabPages){
Bitmap bm = new Bitmap(page.Width, page.Height);
tabControlMain.SelectedTab = page;
page.DrawToBitmap(bm, page.ClientRectangle);
images.Add(bm);
}
}
//Then you can access the images of your TabPages in the list images
//the index of TabPage is corresponding to its image index in the list images
Related
I'm trying to print in winform, it turns out that when I print the document, I get the blank sheet.
This is the code with which I try to print:
private PrintDocument printDocument1 = new PrintDocument();
private string stringToPrint;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ReadPrint();
printDocument1.Print();
}
private void ReadPrint()
{
string docName = "ejemplo.pdf";
string docPath = #"C:\dir1\";
printDocument1.DocumentName = docName;
using (FileStream stream = new FileStream(docPath + docName, FileMode.Open, FileAccess.Read))
using (StreamReader reader = new StreamReader(stream))
{
stringToPrint = reader.ReadToEnd();
}
}
private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
{
int charactersOnPage = 0;
int linesPerPage = 0;
e.Graphics.MeasureString(stringToPrint, this.Font,
e.MarginBounds.Size, StringFormat.GenericTypographic,
out charactersOnPage, out linesPerPage);
e.Graphics.DrawString(stringToPrint, this.Font, Brushes.Black,
e.MarginBounds, StringFormat.GenericTypographic);
stringToPrint = stringToPrint.Substring(charactersOnPage);
e.HasMorePages = (stringToPrint.Length > 0);
}
private void printButton_Click(object sender, EventArgs e)
{
LeerArchivo();
printDocument1.Print();
}
I would like to know if there is a way to correct it or some other way to print the file?Or some example code?
regards
In stringToPrint:
Vb.net has a PrintForm method but C# does not have inbuilt method for printing a Windows Form.
To print a windows form at runtime in C#.net. The base concept involves the capture of the screen image of a Form in jpeg format during runtime and printing the same on a event like Print button click.
print
Are you sure that the stringToPrint is not empty or null ? I'm using the same thing and it works perfectly. You should try to add a print PrintPreviewDialog in case you want to check if the document to be print is not blank. Check your variables first.
e.Graphics.DrawString("SomeString", new Font("Arial", 12, FontStyle.Bold), Brushes.Black, new Point(580, 510));
e.Graphics.DrawString("SomeString1", new Font("Arial", 12, FontStyle.Bold), Brushes.Black, new Point(700, 510));
for the parameter new Point() it is where your text appears via x and y coordinates.
I’m using WinForms. In my form I have a pictureBox and (a From: textbox and a To: Textbox). These textboxes are used to print certain page ranges from a multipage Tif document. The problem is that the application doesn’t print the page ranges. Another problem is that the print preview doesn’t show the correct page, for example If I type number 2 in the From textbox I expect the print preview dialog to show page number 2 from the Tif document, it doesn't show that it shows the wrong page which is page 1.
Test 1: Let’s say if I wanted to print pages 2-5 from the tif document I would type (From: 2 , To: 5).
The weird thing is that the application would only print page 2.
Test 2: I added the line below under print_preview_Setting() and for some reason the print range works using this, but the weird thing is print preview still displays wrong pages.
if (printDialog1.ShowDialog() == DialogResult.OK)
{
currentPrintPage = Convert.ToInt32(From_Pg_txtBox.Text) - 1;
printDocument1.Print();
}
Note: I’ve been printing to PDF for my test cases
Below is a sample Tif Document for Testing
http://www.filedropper.com/tifbordernumberpage
using System.Drawing.Printing;
using System.Drawing.Imaging;
private int currentPrintPage;
private void Form1_Load(object sender, EventArgs e)
{
//using (var dialog = new OpenFileDialog())
//{
// if (dialog.ShowDialog(this) == DialogResult.OK)
// {
// string filename = dialog.FileName;
// pictureBox1.Load(filename);
// }
//}
pictureBox1.Load("C:\\image\\Tif_Document.tif");
}
private void Print_button_Click(object sender, EventArgs e)
{
print_preview_Settings();
// if (printDialog1.ShowDialog() == DialogResult.OK)
// {
// currentPrintPage = Convert.ToInt32(From_Pg_txtBox.Text) - 1;
// printDocument1.Print();
// }
}
private void print_preview_Settings()
{
printPreviewDialog1.Document = printDocument1;
printDocument1.DefaultPageSettings.Margins.Top = 100;
printDocument1.DefaultPageSettings.Margins.Left = 200;
printDocument1.DefaultPageSettings.Margins.Right = 0;
printDocument1.DefaultPageSettings.Margins.Bottom = 0;
currentPrintPage = Convert.ToInt32(From_Pg_txtBox.Text) - 1;
printPreviewDialog1.ShowDialog();
}
private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
{
Image i;
i = Image.FromFile("C:\\image\\Tif_Document.tif");
i.SelectActiveFrame(FrameDimension.Page, currentPrintPage);
//Print while maintating aspect ratio of the image
var img_width = e.PageBounds.Width - e.MarginBounds.Left - Math.Abs(e.MarginBounds.Right - e.PageBounds.Width);
var img_height = e.PageBounds.Height - e.MarginBounds.Top - Math.Abs(e.MarginBounds.Bottom - e.PageBounds.Height);
var img = ResizeAcordingToImage(i, img_width, img_height);
e.Graphics.DrawImage(i,
e.MarginBounds.Left, e.MarginBounds.Top, img.Width, img.Height);
currentPrintPage++; //increment page from the Tif doc
if (currentPrintPage < Convert.ToInt32(to_Pg_txtBox.Text))
{
e.HasMorePages = true;
}
else
{
e.HasMorePages = false;
}
}
private Image ResizeAcordingToImage(Image Source, int boxWidth, int boxHeight)
{
Image resizedImage;
double dbl = (double)Source.Width / (double)Source.Height;
//set height of image to boxHeight and check if resulting width is less than boxWidth,
//else set width of image to boxWidth and calculate new height
if ((int)((double)boxHeight * dbl) <= boxWidth)
{
resizedImage = new Bitmap(Source, (int)((double)boxHeight * dbl), boxHeight);
}
else
{
resizedImage = new Bitmap(Source, boxWidth, (int)((double)boxWidth / dbl));
}
return resizedImage;
}
For some reason, the PrintPage seems to interfere with the active frame of the TIF, so try extracting the image that needs to be displayed:
Image i = Image.FromFile("C:\\image\\Tif_Document.tif");
i.SelectActiveFrame(FrameDimension.Page, currentPrintPage);
using (MemoryStream ms = new MemoryStream()) {
i.Save(ms, ImageFormat.Tiff);
using (Image pageImage = Image.FromStream(ms)) {
var img = ResizeAcordingToImage(pageImage, img_width, img_height);
e.Graphics.DrawImage(pageImage, e.MarginBounds.Left, e.MarginBounds.Top,
img.Width, img.Height);
}
}
This is not a duplicat question- the diffenece beetween my question an the others one is my Controler contail a scroller, so they are more informations can't be printed.
I have a C# application that contains a main form name MainForms. This MainForms has a control mainDisplay. I want to print the entire information what we found on the mainDisplay to the printer.
The problem is the information on the the control is too big, and I have to scroll to see all information.
Someone have any function that allow me to print this control MainDisplay with entire information in it?
This the printscreen of the area of my MainDisplay at the right you see the scrollbar:
I use this Function (Source : Printing a control)
private static void PrintControl(Control control)
{
var bitmap = new Bitmap(control.Width, control.Height);
control.DrawToBitmap(bitmap, new Rectangle(0, 0, control.Width, control.Height));
var pd = new PrintDocument();
pd.PrintPage += (s, e) => e.Graphics.DrawImage(bitmap, 100, 100);
pd.Print();
}
But my problem still can't print all the informations contain in my control, it's just print a small erea, still need print more informations which are not printed.
I find the solution. This is the steps i do :
1 - We have a mainForm, and this main form contain a control mainDisplay with a specific dimension and area, let's say this dimensions is smaller and we get scroll.
2- What i do is i make this mainDisplay Empty.
3- i create an other Control myControlToDisplay. I draw and i put all fields i want without scroll, so this one myControlToDisplay will have a big dimension.
4- on the star-up of my application, i tell to the mainDisplay to load myControlToDisplay. This time all the content of myControlToDisplay will be display on mainDisplay with a scroll. Because mainDisplay have a small area.
5- I write this functions :
Bitmap MemoryImage;
PrintDocument printDoc = new PrintDocument();
PrintDialog printDialog = new PrintDialog();
PrintPreviewDialog printDialogPreview = new PrintPreviewDialog();
Control panel = null;
public void Print(Control pnl)
{
DateTime saveNow = DateTime.Now;
string datePatt = #"yyyy-M-d_hh-mm-ss tt";
panel = pnl;
GetPrintArea(pnl);
printDialog.AllowSomePages = true;
printDoc.PrintPage += new PrintPageEventHandler(Print_Details);
printDialog.Document = printDoc;
printDialog.Document.DocumentName = "Document Name";
//printDialog.ShowDialog();
if (printDialog.ShowDialog() == DialogResult.OK)
{
printDoc.Print();
}
}
public void PrintPreview(Control pnl)
{
DateTime saveNow = DateTime.Now;
string datePatt = #"yyyy-M-d_hh-mm-ss tt";
panel = pnl;
GetPrintArea(pnl);
printDoc.PrintPage += new PrintPageEventHandler(Print_Details);
printDialogPreview.Document = printDoc;
printDialogPreview.Document.DocumentName = "Document Name";
//printDialog.ShowDialog();
if (printDialogPreview.ShowDialog() == DialogResult.OK)
{
printDoc.Print();
}
}
private void Print_Details(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
RectangleF marginBounds = e.MarginBounds;
DateTime saveNow = DateTime.Now;
string datePatt = #"M/d/yyyy hh:mm:ss tt";
//String dtString = saveNow.ToString(datePatt);
// create header and footer
string header = "Put all information you need to display on the Header";
string footer = "Print date : " + saveNow.ToString(datePatt);
Font font = new Font("times new roman", 10, System.Drawing.FontStyle.Regular);
Brush brush = new SolidBrush(Color.Black);
// measure them
SizeF headerSize = e.Graphics.MeasureString(header, font);
SizeF footerSize = e.Graphics.MeasureString(footer, font);
// draw header
RectangleF headerBounds = new RectangleF(marginBounds.Left-80, marginBounds.Top-80, marginBounds.Width, headerSize.Height);
e.Graphics.DrawString(header, font, brush, headerBounds);
// draw footer
RectangleF footerBounds = new RectangleF(marginBounds.Left-80, marginBounds.Bottom - footerSize.Height+80, marginBounds.Width, footerSize.Height);
e.Graphics.DrawString(footer, font, brush, footerBounds);
// dispose objects
font.Dispose();
brush.Dispose();
}
public void GetPrintArea(Control 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));
}
protected override void OnPaint(PaintEventArgs e)
{
if (MemoryImage != null)
{
e.Graphics.DrawImage(MemoryImage, 0, 0);
base.OnPaint(e);
}
}
void PrintDoc_PrintPage(object sender, PrintPageEventArgs e)
{
Rectangle pageArea = e.PageBounds;
Rectangle m = e.MarginBounds;
if ((double)MemoryImage.Width / (double)MemoryImage.Height > (double)m.Width / (double)m.Height) // image is wider
{
m.Height = (int)((double)MemoryImage.Height / (double)MemoryImage.Width * (double)m.Width);
}
else
{
m.Width = (int)((double)MemoryImage.Width / (double)MemoryImage.Height * (double)m.Height);
}
e.Graphics.DrawImage(MemoryImage, m);
}
6 -And finally we suppose that we have two buttons, one to Print and the other one to print preview.
You just have to call this function :
private void PrintButton_Click(object sender, EventArgs e)
{
try
{
Print(mainDisplay.getCurentPanel());
}
catch (Exception exp)
{
MessageBox.Show("Error: \n" + exp.Message);
}
}
private void PrintPreviewButton_Click(object sender, EventArgs e)
{
try
{
PrintPreview(mainDisplay.getCurentPanel());
}
catch (Exception exp)
{
MessageBox.Show("Error: \n" + exp.Message);
}
}
Hope it will help someone :)
good luck
Using the code example from MSDN on how to print a windows form, I have the altered mine to bring up the printer options first and then print, but I keep receiving a blank page. Using CopyFromScreen, I am giving the coordinates of the forms source X & Y, but for the destination I have tried 0 as well as this.Location.X & Y. Is there another way to capture the image?
private void printButton_Click(object sender, EventArgs e)
{
CaptureScreen();
printDialog1.AllowSomePages = true;
printDialog1.ShowHelp = true;
printDialog1.Document = printDoc1;
DialogResult result = printDialog1.ShowDialog();
if (result == DialogResult.OK)
{
printDoc1.Print();
}
}
private void CaptureScreen()
{
Graphics myGraphics = this.CreateGraphics();
Size s = this.Size;
memoryImage = new Bitmap(s.Width, s.Height, myGraphics);
Graphics memoryGraphics = Graphics.FromImage(memoryImage);
memoryGraphics.CopyFromScreen(this.Location.X, this.Location.Y, 0, 0, s);
}
void printDoc1_PrintPage(object sender, PrintPageEventArgs e)
{
e.Graphics.DrawImage(memoryImage, 0, 0);
}
I have a window form. I want to print the contents of the form without the window appearance. I mean I want to print it like a receipt, without window borders. How do I do this?
You can take the MSDN example on how to Print to a Windows Form, Change the Surface being printed from the Form to a Panel Control, which will enable you to print without Borders. Your Contents will have to be added to the Panel instead of the Form but it will work. Here is a modified example of the MSDN example.
public class Form1 : Form
{
private Panel printPanel = new Panel();
private Button printButton = new Button();
private PrintDocument printDocument1 = new PrintDocument();
public Form1()
{
printPanel.Size = this.ClientSize;
this.Controls.Add(printPanel);
printButton.Text = "Print Form";
printButton.Click += new EventHandler(printButton_Click);
printDocument1.PrintPage += new PrintPageEventHandler(printDocument1_PrintPage);
printPanel.Controls.Add(printButton);
}
void printButton_Click(object sender, EventArgs e)
{
CaptureScreen();
printDocument1.Print();
}
Bitmap memoryImage;
private void CaptureScreen()
{
Graphics myGraphics = printPanel.CreateGraphics();
Size s = printPanel.Size;
memoryImage = new Bitmap(s.Width, s.Height, myGraphics);
Graphics memoryGraphics = Graphics.FromImage(memoryImage);
Point screenLoc = PointToScreen(printPanel.Location); // Get the location of the Panel in Screen Coordinates
memoryGraphics.CopyFromScreen(screenLoc.X, screenLoc.Y, 0, 0, s);
}
private void printDocument1_PrintPage(System.Object sender,
System.Drawing.Printing.PrintPageEventArgs e)
{
e.Graphics.DrawImage(memoryImage, 0, 0);
}
public static void Main()
{
Application.Run(new Form1());
}
}
you can just get a blank screen by doing something like this
this.FormBorderStyle = System.Windows.Forms.FormsBorderStyle.None;
this.ControlBox = false;
this.Text = String.Empty;