Как я могу предварительно измерить строку перед печатью?
Здравствуйте, я изучаю программирование на C# VS 2010 EE и подаю заявку на заполнение предварительно напечатанной формы. Эта форма имеет несколько мест в разных координатах. Три из коробок на бумаге являются многострочными 5” W x 2” H коробками.
Я уже создал форму окна с одним TextBox
за каждое место на бумажном бланке.
Дело в том, что при вводе информации в эти многострочные текстовые поля мне нужно знать, сколько строк осталось на бумаге, чтобы ввести больше текста, а также, когда прекратить печатать, потому что в поле PrePrinted больше нет свободного места.
Я провел большой поиск, но все, что я нашел, - это измерение на экране, которое не соответствует конечному результату на бумаге.
Другими словами, мне нужно знать, как определить размеры строк на бумаге при вводе текста в текстовые поля и сравнить ее с пространством, доступным в предварительно напечатанной форме, чтобы я мог остановиться, прежде чем она переместится через нижняя граница коробки на бумаге.
Первая коробка на бумаге имеет ширину 5 дюймов и высоту 2 дюйма, начиная сnew RectangleF(60.0F, 200.0F, 560.0F, 200.0F)
". Я понимаю, что эти цифры составляют сотые доли дюйма.
Все это с учетом того, что я не могу ограничить текстовые поля количеством символов, потому что не все символы занимают одно и то же пространство, как H != I;
M != l;
и т.п.
Спасибо заранее за вашу помощь. Сегодня, 5 сентября 2011 года, на основании ваших комментариев и предложений я изменил код для использования Graphics.MeasureString .
Это код, который у меня сейчас есть с Graphics.MeasureString и только одним richTextBox: отлично работает из события printDocument1_PrintPage, но я не знаю, как заставить его работать из события richTextBox1_TextChanged.
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;
}
}
}
3 ответа
Я думаю, что это то, что вы после.
Juat убедитесь, что ваш графический объект является 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
}
}
}
Информация в текстовом поле будет сохранена в базе данных и распечатана в предварительно напечатанной форме через некоторое время. Поскольку пространство в каждой коробке на бумаге ограничено, я должен был убедиться, что то, что когда-либо попадает в базу данных, не больше, чем то, что может обрабатывать каждая ячейка на бумажной форме. Это код, позволяющий пользователю не вводить больше строк, чем может поместиться в 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;
}
}
}
Если я прав, вы можете использовать класс FormattedText для форматирования перед печатью. Затем вы можете проверить свойство ширины FormatedText.
Здесь есть хорошее руководство по печати: http://www.switchonthecode.com/tutorials/printing-in-wpf. Вторая часть больше ориентирована на нумерацию страниц (с чем, я думаю, вы имеете дело): http://www.switchonthecode.com/tutorials/wpf-printing-part-2-pagination. FormattedText появляется здесь.