问题
Hello, I am learning programming with C# VS 2010 EE and I’m making an application to fill up a preprinted form. This form has several places in different coordinates. Three of the boxes on the paper are multiline 5” W x 2” H boxes.
I already created the windows form with one TextBox
for each place on the paper form.
The thing is that when entering the info in these multiline TextBoxes I need to know how many lines are left on the paper to enter more text, and also, when to stop typing because there is no more space available in the PrePrinted box.
I’ve done a lot of search but everything I have found is about measuring on the screen, which does not match the final result on the paper.
In other words, I need to know how to find out what are going to be the string dimensions on the paper while is being typed into the TextBoxes and compare it with the space available on the PrePrinted form so I can stop before it goes over the bottom border of the box on the paper.
The first box on the paper is 5” in width by 2” in height, starting at “new RectangleF(60.0F, 200.0F, 560.0F, 200.0F)
”. I understand those numbers are hundredths of an inch.
All of this, taking in to account that I can not limit the TextBoxes by quantity of characters because not all characters occupy the same space, like H != I;
M != l;
etc.
Thank you in advance for your help. Today Sep 05 2011, based on your comments and suggestions I’ve changed the code to use Graphics.MeasureString .
This is the code I have now with the Graphics.MeasureString and only one richTextBox: Is working perfectly from the printDocument1_PrintPage event, but I have no idea how to make it work from the richTextBox1_TextChanged event.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Printing;//Needed for the PrintDocument()
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Printing
{
public partial class Form1 : Form
{
private Font printFont1;
string strPrintText;
public Form1()
{
InitializeComponent();
}
private void cmdPrint_Click(object sender, EventArgs e)
{
try
{
PrintDocument pdocument = new PrintDocument();
pdocument.PrintPage += new PrintPageEventHandler
(this.printDocument1_PrintPage);
pdocument.Print();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public void printDocument1_PrintPage (object sender,
System.Drawing.Printing.PrintPageEventArgs e)
{
strPrintText = richTextBox1.Text.ToString();
printFont1 = new Font("Times New Roman", 10); //I had to remove this line from the btnPrintAnexo1_Click
Graphics g = e.Graphics;
StringFormat format1 = new StringFormat();
RectangleF rectfText;
int iCharactersFitted, iLinesFitted;
rectfText = new RectangleF(60.0F, 200.0F, 560.0F, 200.0F);
// The following e.Graphics.DrawRectangle is
// just for debuging with printpreview
e.Graphics.DrawRectangle(new Pen(Color.Black, 1F),
rectfText.X, rectfText.Y, rectfText.Width, rectfText.Height);
format1.Trimming = StringTrimming.Word; //Word wrapping
//The next line of code "StringFormatFlags.LineLimit" was commented so the condition "iLinesFitted > 12" could be taken into account by the MessageBox
// Use next line of code if you don't want to show last line, which will be clipped, in rectangleF
//format1.FormatFlags = StringFormatFlags.LineLimit;
//Don't use this next line of code. Some how it gave me a wrong linesFilled
//g.MeasureString(strPrintText, font, rectfFull.Size,
//StringFormat.GenericTypographic, out iCharactersFitted, out iLinesFilled);
//Use this one instead:
//Here is where we get the quantity of characters and lines used
g.MeasureString(strPrintText, printFont1, rectfText.Size, format1, out iCharactersFitted, out iLinesFitted);
if (strPrintText.Length == 0)
{
e.Cancel = true;
return;
}
if (iLinesFitted > 12)
{
MessageBox.Show("Too many lines in richTextBox1.\nPlease reduce text entered.");
e.Cancel = true;
return;
}
g.DrawString(strPrintText, printFont1, Brushes.Black, rectfText, format1);
g.DrawString("iLinesFilled = Lines in the rectangle: " + iLinesFitted.ToString(), printFont1, Brushes.Black,
rectfText.X, rectfText.Height + rectfText.Y);
g.DrawString("iCharactersFitted = Characters in the rectangle: " + iCharactersFitted.ToString(), printFont1, Brushes.Black,
rectfText.X, rectfText.Height + rectfText.Y + printFont1.Height);
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
//***I don’t know what to type here.***
if (iLinesFitted == 13)
{
MessageBox.Show("Too many lines in richTextBox1.\nPlease erase some characters.");
}
}
private void cmdPrintPreview_Click(object sender, EventArgs e)
{
printPreviewDialog1.ShowDialog();
}
private void printDocument1_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
{
// strPrintText = richTextBox1.Text;
}
}
}
回答1:
I think that this is what you are after.
MeasureString(...)
Juat make sure that your graphics object is a PrintDocument.
using System;
using System.Drawing;
using System.Drawing.Printing;
using System.Windows.Forms;
namespace GraphicsHandler
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
// Check the width of the text whenever it is changed.
if (checkTextWillFit(textBox1.Text) == true)
{
MessageBox.Show("Entered test is too wide, please reduce the number of characters.");
}
}
private bool checkTextWillFit(string enteredText)
{
// Create a handle to the graphics property of the PrintPage object
Graphics g = pd.PrinterSettings.CreateMeasurementGraphics();
// Set up a font to be used in the measurement
Font myFont = new Font("Arial", 12, FontStyle.Regular, GraphicsUnit.Millimeter);
// Measure the size of the string using the selected font
// Return true if it is too large
if (g.MeasureString(enteredText, myFont).Width > 100)
{
return true;
}
else
{
return false;
}
}
PrintDocument pd = null;
private void Form1_Load(object sender, EventArgs e)
{
// Initialise the print documnet used to render the printed page
pd = new PrintDocument();
// Create the event handler for when the page is printed
pd.PrintPage += new PrintPageEventHandler(pd_PrintPage);
}
void pd_PrintPage(object sender, PrintPageEventArgs e)
{
// Page printing logic here
}
}
}
回答2:
The information in the text box will be stored in a database and printed on a preprinted form some time. Since the space in each box on the paper is limited, I had to make sure that what ever goes to the database is not more than what the each cell on the paper form can handle. This is the code to avoid the user to enter more lines than can fit in the rectangleF:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Printing;//Needed for the PrintDocument()
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Printing
{
public partial class Form1 : Form
{
private Font printFont1;
string strPrintText;
public Form1()
{
InitializeComponent();
}
//PrintDocument printDocument1 = null; In ny case it makes this error: 'Printing.Form1' already contains a definition for 'primtDocument1'
private void Form1_Load(object sender, EventArgs eP)
{
PrintDocument pd = new PrintDocument();
pd.PrintPage += new PrintPageEventHandler
(this.printDocument1_PrintPage);
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
// Check the width of the text whenever it is changed.
if (checkTextWillFit(richTextBox1.Text) == true)
{
MessageBox.Show("\nEntered text pruduces too many lines. \n\nPlease reduce the number of characters.", "Too Many Lines");
}
}
private bool checkTextWillFit(string enteredText)
{
StringFormat format1 = new StringFormat();
format1.Trimming = StringTrimming.Word; //Word wrapping
RectangleF rectfText;
int iCharactersFitted, iLinesFitted;
rectfText = new RectangleF(60.0F, 200.0F, 560.0F, 200.0F);
// Create a handle to the graphics property of the PrintPage object
Graphics g = printDocument1.PrinterSettings.CreateMeasurementGraphics();
// Set up a font to be used in the measurement
Font myFont = new Font("Times New Roman", 10, FontStyle.Regular);
// Measure the size of the string using the selected font
// Return true if it is too large
g.MeasureString(enteredText, myFont, rectfText.Size, format1, out iCharactersFitted, out iLinesFitted);
if (iLinesFitted > 12)
{
return true;
}
else
{
return false;
}
}
private void cmdPrint_Click(object sender, EventArgs e)
{
try
{
PrintDocument pdocument = new PrintDocument();
pdocument.PrintPage += new PrintPageEventHandler
(this.printDocument1_PrintPage);
pdocument.Print();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
public void printDocument1_PrintPage(object sender,
System.Drawing.Printing.PrintPageEventArgs e)
{
strPrintText = richTextBox1.Text.ToString();
printFont1 = new Font("Times New Roman", 10); //I had to remove this line fromthe btnPrintAnexo1_Click
Graphics g = e.Graphics;
//float cyFont = printFont1.GetHeight(g);
StringFormat format1 = new StringFormat();
format1.Trimming = StringTrimming.Word; //Word wrapping
RectangleF rectfText;
int iCharactersFitted, iLinesFitted;
rectfText = new RectangleF(60.0F, 200.0F, 560.0F, 200.0F);
// The following e.Graphics.DrawRectangle is
// just for debuging with printpreview
e.Graphics.DrawRectangle(new Pen(Color.Black, 1F),
rectfText.X, rectfText.Y, rectfText.Width, rectfText.Height);
//Here is where we get the quantity of characters and lines used
g.MeasureString(strPrintText, printFont1, rectfText.Size, format1, out iCharactersFitted, out iLinesFitted);
if (strPrintText.Length == 0)
{
e.Cancel = true;
return;
}
if (iLinesFitted > 12)
{
MessageBox.Show("Too many lines in richTextBox1.\nPlease reduce text entered.");
e.Cancel = true;
return;
}
g.DrawString(strPrintText, printFont1, Brushes.Black, rectfText, format1);
g.DrawString("iLinesFilled = Lines in the rectangle: " + iLinesFitted.ToString(), printFont1, Brushes.Black,
rectfText.X, rectfText.Height + rectfText.Y);
g.DrawString("iCharactersFitted = Characters in the rectangle: " + iCharactersFitted.ToString(), printFont1, Brushes.Black,
rectfText.X, rectfText.Height + rectfText.Y + printFont1.Height);
}
private void cmdPrintPreview_Click(object sender, EventArgs e)
{
printPreviewDialog1.ShowDialog();
}
private void printDocument1_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
{
// strPrintText = richTextBox1.Text;
}
}
}
回答3:
If I'm right, you can use a class called FormattedText to format it before printing. Then you can check the FormatedText's width property.
There's a good tutorial on printing here: http://www.switchonthecode.com/tutorials/printing-in-wpf. The second part is focused more on pagination (which is what I think you are dealing with): http://www.switchonthecode.com/tutorials/wpf-printing-part-2-pagination. FormattedText appears here.
来源:https://stackoverflow.com/questions/7054922/how-can-i-pre-measure-a-string-before-is-printed