Pagefeed does not work correctly after first print - c#

Using instructions, I found on stackoverflow I can print across multiple pages. But if I print the document multiple times without leaving the app, the pages are combined.
Result: First time 4 separate pages after 4 prints only 1 single page.
Here is my code (the form just has a single button). I think I need to reset something somewhere but can't figure it out. Appreciate your help!
using System;
using System.Drawing;
using System.Drawing.Printing;
using System.Windows.Forms;
namespace PrintIt
{
public partial class Form1 : Form
{
int N, Y, PageNr;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
printDocument1.DocumentName = "Test Print";
printDialog1.Document = printDocument1;
printDocument1.PrintPage += new PrintPageEventHandler(printit);
// Initialize the dialog's PrinterSettings property to hold user
// defined printer settings.
pageSetupDialog1.PageSettings =
new System.Drawing.Printing.PageSettings();
//Show the dialog storing the result.
DialogResult result = pageSetupDialog1.ShowDialog();
if (result == DialogResult.OK)
{
printDocument1.DefaultPageSettings.PaperSize = pageSetupDialog1.PageSettings.PaperSize;
printDocument1.DefaultPageSettings.Landscape = pageSetupDialog1.PageSettings.Landscape;
string message = "Would you like to view the print preview first?";
string caption = "Print Preview";
MessageBoxButtons buttons = MessageBoxButtons.YesNo;
Y = 0;
N = 0;
PageNr = 1;
result = MessageBox.Show(message, caption, buttons); // Displays the MessageBox.
if (result == System.Windows.Forms.DialogResult.Yes)
{
printPreviewDialog1.Document = printDocument1;
((ToolStripButton)((ToolStrip)printPreviewDialog1.Controls[1]).Items[0]).Enabled = false;//disable the direct print from printpreview.as when we click that Print button PrintPage event fires again.
printPreviewDialog1.ShowDialog();
}
if (printDialog1.ShowDialog() == DialogResult.OK)
{
printDocument1.Print();
}
}
}
private void printit(System.Object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
Font LFont = new Font("Arial", 12);
float fontHeight = LFont.GetHeight();
int startY = 40;
int pageHeight = printDocument1.DefaultPageSettings.PaperSize.Height;
e.Graphics.DrawString("Page:" + PageNr, LFont, Brushes.Black, PageNr * 100, 10);
for (int i = Y; i < 200; i++)
{
e.Graphics.DrawString("Line: " + i, LFont, Brushes.Black, PageNr * 100, startY + N);
N += (int)fontHeight;
if (startY + N >= pageHeight - 100)
{
e.HasMorePages = true;
N = 0;
Y = i;
PageNr += 1;
return;
}
}
e.HasMorePages = false;
}
}
}

Finally figured it out. At first, I added the necessary print objects from the toolbox onto the form design. While this works it does not handle multiple pages correctly.
I now removed those objects from the form design and added them in code when the button is pressed:
PrintPreviewDialog printPreviewDialog1 = new PrintPreviewDialog();
PrintDocument printDocument1 = new PrintDocument();
PageSetupDialog pageSetupDialog1 = new PageSetupDialog();
PrintDialog printDialog1 = new PrintDialog();
Works like a charm!

Related

The TextBoxes locations get modified before the repaint event is performed

I have a panel and on this panel, I create a number of TextBoxes, one under the other. The number of TextBoxes is greater than the vertical size of the panel can accommodate.
I have two problems:
1. The first TextBox appears at a large vertical distance from the top of the panel, even though its vertical coordinate is 5.
2. I want to automatically scroll to the bottom of the panel so that the last TextBoxes get visible, but I am unable to do that.
The first TextBoxes remain visible.
Here is the code I use:
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;
namespace TestPanelScroll
{
public partial class Form1 : Form
{
private const int _verticalSpacing = 1;
public Form1()
{
InitializeComponent();
this.StartPosition = FormStartPosition.CenterScreen;
this.BackColor = Color.BurlyWood;
this.ClientSize = new Size(800, 800);
this.SuspendLayout();
panelLeftForNodeCreationAndNodeMembersEditingMode = new Panel();
panelLeftForNodeCreationAndNodeMembersEditingMode.SuspendLayout();
panelLeftForNodeCreationAndNodeMembersEditingMode.Location = new Point(3, 56);
panelLeftForNodeCreationAndNodeMembersEditingMode.Size = new Size(461, 187);
panelLeftForNodeCreationAndNodeMembersEditingMode.Name = "panelLeftForNodeCreationAndNodeMembersEditingMode";
panelLeftForNodeCreationAndNodeMembersEditingMode.BorderStyle = BorderStyle.Fixed3D;
panelLeftForNodeCreationAndNodeMembersEditingMode.Visible = true;
panelLeftForNodeCreationAndNodeMembersEditingMode.CausesValidation = false;
panelLeftForNodeCreationAndNodeMembersEditingMode.TabStop = false;
panelLeftForNodeCreationAndNodeMembersEditingMode.TabIndex = 0;
panelLeftForNodeCreationAndNodeMembersEditingMode.BackColor = Color.LightGray;
panelLeftForNodeCreationAndNodeMembersEditingMode.SetAutoScrollMargin(0, 40);
panelLeftForNodeCreationAndNodeMembersEditingMode.HorizontalScroll.Maximum = 0;
panelLeftForNodeCreationAndNodeMembersEditingMode.AutoScroll = false;
panelLeftForNodeCreationAndNodeMembersEditingMode.HorizontalScroll.Visible = false;
panelLeftForNodeCreationAndNodeMembersEditingMode.AutoScroll = true;
panelLeftForNodeCreationAndNodeMembersEditingMode.Parent = this;
this.Controls.Add(panelLeftForNodeCreationAndNodeMembersEditingMode);
panelLeftForNodeCreationAndNodeMembersEditingMode.SendToBack();
panelLeftForNodeCreationAndNodeMembersEditingMode.ResumeLayout(false);
panelLeftForNodeCreationAndNodeMembersEditingMode.PerformLayout();
TextBox currentTextBox = null;
int xCoordinate = 30;
for (int i = 1; i <= 37; i++)
{
currentTextBox = new TextBox();
currentTextBox.Name = i.ToString();
currentTextBox.Size = new Size(85, 20);
currentTextBox.Tag = i.ToString();
currentTextBox.TabIndex = i - 1;
currentTextBox.TextAlign = HorizontalAlignment.Center;
currentTextBox.Text = currentTextBox.Name;
currentTextBox.Enabled = true;
currentTextBox.ReadOnly = true;
currentTextBox.CausesValidation = true;
currentTextBox.TabStop = true;
currentTextBox.BackColor = Color.DarkGray;
currentTextBox.Parent = panelLeftForNodeCreationAndNodeMembersEditingMode;
int yCoordinate = yCoordinate = 0 + (i - 1) * _verticalSpacing * 33 + _verticalSpacing * 5;
currentTextBox.Location = new Point(xCoordinate, yCoordinate);
textBox1.AppendText("TextBox " + currentTextBox.Name + " verticalCoordinate = " + yCoordinate.ToString() + Environment.NewLine);
int value = (currentTextBox.Location.Y + currentTextBox.Height) * 2 + _verticalSpacing * 40;
panelLeftForNodeCreationAndNodeMembersEditingMode.AutoScrollPosition = new Point(0, value);
panelLeftForNodeCreationAndNodeMembersEditingMode.VerticalScroll.Maximum = 300;
int minimum = panelLeftForNodeCreationAndNodeMembersEditingMode.VerticalScroll.Minimum;
int maximum = panelLeftForNodeCreationAndNodeMembersEditingMode.VerticalScroll.Maximum;
//panelLeftForNodeCreationAndNodeMembersEditingMode.VerticalScroll.Value = value;
//panelLeftForNodeCreationAndNodeMembersEditingMode.VerticalScroll.Value = value;
panelLeftForNodeCreationAndNodeMembersEditingMode.SetAutoScrollMargin(0, 40);
panelLeftForNodeCreationAndNodeMembersEditingMode.ScrollControlIntoView(currentTextBox);
panelLeftForNodeCreationAndNodeMembersEditingMode.PerformLayout();
}
this.ResumeLayout();
}
private Panel panelLeftForNodeCreationAndNodeMembersEditingMode;
private void button1_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
I use Visual Studio 2010.
Any idea would be greatly appreciated.
Thank you in advance.
My intention is to understand what I am doing wrong and how to correct my code and not to find a workaround (a different way to program it).

How to apply a Focus() function on Dynamically Created TextBox in windows forms?

When dynamically creating textBoxes how can we make one of the textBoxes have the Focus() function on it?
namespace Dinamik_Arac
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
for (int i = 1; i <= 5; i++)
{
TextBox txt = new TextBox();
Point txtKonum = new Point(300, i * 30);
txt.Location = txtKonum;
txt.Name = "TextBox" + i;
txt.Text = i.ToString();
this.Controls.Add(txt);
}
}
}
}
Simply writing TextBox4.Focus() into the for loop is not working.
for (int i = 1; i <= 5; i++)
{
TextBox txt = new TextBox();
Point txtKonum = new Point(300, i * 30);
txt.Location = txtKonum;
txt.Name = "TextBox" + i;
txt.Text = i.ToString();
if(i == 4)
{
txt.Focus();
}
this.Controls.Add(txt);
}
This code does not work either.
enter image description here
As you can see in the picture there is no cursor on the 4th textBox.
Solved,
just put the this.Controls.Add(txt); code before the if statement,
{
TextBox txt = new TextBox();
Point txtKonum = new Point(300, i * 30);
txt.Location = txtKonum;
txt.Name = "TextBox" + i;
txt.Text = i.ToString();
this.Controls.Add(txt);
if(i == 4)
{
txt.Focus();
}
}
I've been playing around with this problem looking for an alternative and more versatile approach, and I came up with this method for giving focus to your your 4th iteration of dynamically created textboxes:
string focusedTextBox = "TextBoxName";//in this case "Textbox4"
Control focusControl = this.Controls[focusedTextBox];
focusControl.Focus();
In your application, it would look like this:
private void button1_Click(object sender, EventArgs e)
{
for (int i = 1; i <= 5; i++)
{
TextBox txt = new TextBox();
Point txtKonum = new Point(300, i * 30);
txt.Location = txtKonum;
txt.Name = "TextBox" + i;
txt.Text = i.ToString();
this.Controls.Add(txt);
}
Control focusControl = this.Controls["Textbox4"];
focusControl.Focus();
}
The obvious major advantage to this approach is that it will work from other places in the program. The only thing that has to be taken into account when calling this from a seperate method is that if the control.name doesn't exist an exception will be thrown, so it would probably be a good idea to set up some sort of safeguard or exception handling for that usage.

C# how to print out an array of PictureBox in multiple pages

using C#, I wrote the below code to print out images in an array (size = totalToPrint) of Picturebox pictureBoxArr[] each in size of 100x100 pixel. I want to print them vertically with the 20-pixel distance between them heightDistanceBetweenImages the problem is that it only prints on 1 page (say letter size) no matter how many images ( then it only prints 8 images and dismisses the rest). How can I solve this problem, and print it on multiple pages?
int totalToPrint;
int xFirstAncorPoint = 100;
int yFirstAncorPoint = 100;
int ImagSize = 100; // Squre of 100x100 pixel
int heightDistanceBetweenImages = 20;
PrintDialog pd = new PrintDialog();
PrintDocument pDoc = new PrintDocument();
pDoc.PrintPage += PrintPicture;
pd.Document = pDoc;
if (pd.ShowDialog() == DialogResult.OK)
{
pDoc.Print();
}
}
public void PrintPicture(Object sender, PrintPageEventArgs e)
{
Bitmap bmp1 = new Bitmap(ImagSize , totalToPrint * (ImagSize + heightDistanceBetweenImages));
for (int i = 0; i < totalToPrint; i++)
{
pictureBoxArr[i].DrawToBitmap(bmp1, new Rectangle(0, i * (heightDistanceBetweenImages + ImagSize), pictureBoxArr[0].Width, pictureBoxArr[0].Height));
}
e.Graphics.DrawImage(bmp1, xFirstAncorPoint, yFirstAncorPoint);
bmp1.Dispose();
}
You are about half way there. PrintDocument would be your future reference.
The PrintPage gives you more than just a drawing space; it also has your page bounds, page margins, etc. It also has HasMorePages property that you set if you need to print more pages. This property defaults to false, so you were only printing 1 page. Also if anything is outside the bounds of the page, it would not print that. With a little change here and there, you would end up with something like this.
// using queue to manage images to print
Queue<Image> printImages = new Queue<Image>();
int totalToPrint;
int xFirstAncorPoint = 100;
int yFirstAncorPoint = 100;
int ImagSize = 100; // Squre of 100x100 pixel
int heightDistanceBetweenImages = 20;
private void btnPrintTest_Click(object sender, EventArgs e) {
PrintDialog pd = new PrintDialog();
PrintDocument pDoc = new PrintDocument();
pDoc.PrintPage += PrintPicture;
pd.Document = pDoc;
if (pd.ShowDialog() == DialogResult.OK) {
// add image references to printImages queue.
for (int i = 0; i < pictureBoxArr.Length; i++) {
printImages.Enqueue(pictureBoxArr[i].Image);
}
pDoc.Print();
}
}
private void PrintPicture(object sender, PrintPageEventArgs e) {
int boundsHeight = e.MarginBounds.Height; // Get height of bounds that we are expected to print in.
int currentHeight = yFirstAncorPoint;
while (currentHeight <= boundsHeight && printImages.Count > 0) {
var nextImg = printImages.Peek();
int nextElementHeight = nextImg.Height + heightDistanceBetweenImages;
if (nextElementHeight + currentHeight <= boundsHeight) {
e.Graphics.DrawImage(nextImg, new PointF(xFirstAncorPoint, currentHeight + heightDistanceBetweenImages));
printImages.Dequeue();
}
currentHeight += nextElementHeight;
}
// how we specify if we may have more pages to print
e.HasMorePages = printImages.Count > 0;
}
Hopefully this gets you on the right path and with some minor tweaks for your code, you will have what you need.

Using Print Page Range

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);
}
}

Printing Multiple Pages in a Winform application

I am attempting to print something using a C# Winforms application. I can't seem to understand how multiple pages works. Let's say I have the following code in my constructor:
private string _stringToPrint;
_stringToPrint = "";
for (int i = 0; i < 120; i++)
{
_stringToPrint = _stringToPrint + "Line " + i.ToString() + Environment.NewLine;
}
Then I have this code on my button click event:
private void MnuFilePrintClick(object sender, EventArgs e)
{
var pd = new PrintDocument();
pd.PrintPage += pd_PrintPage;
var z = new PrintPreviewDialog { Document = pd };
z.ShowDialog(this);
}
void pd_PrintPage(object sender, PrintPageEventArgs e)
{
Graphics g = e.Graphics;
var font = new Font("Arial", 10f, FontStyle.Regular);
g.DrawString(_stringToPrint, font, Brushes.Black, new PointF(10f, 10f));
}
Right now, when I run this code, it is giving me one page and after like 70 lines, it just runs off the paper. How would I print this string so that it prints enough for one page, then runs over to the second page, etc..?
You could have a counter and set the amount of lines you want per page like so:
private string[] _stringToPrint = new string[100]; // 100 is the amount of lines
private int counter = 0;
private int amtleft = _stringToPrint.Length;
private int amtperpage = 40; // The amount of lines per page
for (int i = 0; i < 120; i++)
{
_stringToPrint[i] ="Line " + i.ToString();
}
Then in pd_PrintPage:
void pd_PrintPage(object sender, PrintPageEventArgs e)
{
int currentamt = (amtleft > 40)?40:amtleft;
Graphics g = e.Graphics;
var font = new Font("Arial", 10f, FontStyle.Regular);
for(int x = counter; x < (currentamt+counter); x++)
{
g.DrawString(_stringToPrint[x], font, Brushes.Black, new PointF(10f, (float)x*10));
// x*10 is just so the lines are printed downwards and not on top of each other
// For example Line 2 would be printed below Line 1 etc
}
counter+=currentamt;
amtleft-=currentamt;
if(amtleft<0)
e.HasMorePages = true;
else
e.HasMorePages = false;
// If e.HasMorePages is set to true and the 'PrintPage' has finished, it will print another page, else it wont
}
I have had bad experiences with e.HasMorePages so this may not work.
Let me know if this works and I hope it helps!

Categories

Resources