6 votes

Comment puis-je mesurer une chaîne avant qu'elle ne soit imprimée ?

This is a sketch of the paper form Bonjour, je suis en train d'apprendre à programmer avec C# VS 2010 EE et je suis en train de faire une application pour remplir un formulaire préimprimé. Ce formulaire a plusieurs emplacements dans des coordonnées différentes. Trois des cases du papier sont des cases multilignes de 5" de large x 2" de haut.

J'ai déjà créé le formulaire Windows avec un TextBox pour chaque place sur le formulaire papier.

En effet, lorsque je saisis des informations dans ces boîtes de texte multilignes, j'ai besoin de savoir combien de lignes il reste sur le papier pour saisir davantage de texte, et aussi quand je dois arrêter de taper parce qu'il n'y a plus d'espace disponible dans la boîte préimprimée.

J'ai fait beaucoup de recherches, mais tout ce que j'ai trouvé concerne la mesure à l'écran, qui ne correspond pas au résultat final sur le papier.

En d'autres termes, j'ai besoin de savoir comment déterminer les dimensions de la chaîne de caractères sur le papier pendant qu'elle est saisie dans les boîtes de texte et de les comparer à l'espace disponible sur le formulaire préimprimé afin de pouvoir m'arrêter avant qu'elle ne dépasse le bord inférieur de la boîte sur le papier.

La première case du papier mesure 5" de largeur sur 2" de hauteur et commence à ". new RectangleF(60.0F, 200.0F, 560.0F, 200.0F) ". Je comprends que ces chiffres correspondent à des centièmes de pouce.

Tout cela, en tenant compte du fait que je ne peux pas limiter les TextBox par quantité de caractères parce que tous les caractères n'occupent pas le même espace, par exemple H != I; M != l; etc.

Merci d'avance pour votre aide. Aujourd'hui, le 05 septembre 2011, sur la base de vos commentaires et suggestions, j'ai modifié le code pour utiliser Graphics.MeasureString .

Voici le code que j'ai maintenant avec le Graphics.MeasureString et une seule richTextBox : Fonctionne parfaitement à partir de l'événement printDocument1_PrintPage, mais je n'ai aucune idée de comment le faire fonctionner à partir de l'événement 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;
    }
  }
}

6voto

Jason James Points 577

Je pense que c'est ce que vous recherchez.

MesureString(...)

Assurez-vous que votre objet graphique est un 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            
        }
    } 
}

1voto

Alex Points 75

Les informations contenues dans la zone de texte seront stockées dans une base de données et imprimées sur un formulaire préimprimé à un moment donné. Comme l'espace dans chaque case du papier est limité, je devais m'assurer que ce qui va dans la base de données ne dépasse pas ce que chaque cellule du formulaire papier peut contenir. Voici le code qui évite à l'utilisateur d'entrer plus de lignes qu'il ne peut en contenir dans le 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;
        }

    }
}

0voto

tinchou Points 334

Si j'ai raison, vous pouvez utiliser une classe appelée FormattedText pour le formater avant l'impression. Vous pouvez ensuite vérifier la propriété width du FormatedText.

Un bon tutoriel sur l'impression est disponible ici : http://www.switchonthecode.com/tutorials/printing-in-wpf . La deuxième partie est davantage axée sur la pagination (ce qui est, je pense, votre cas) : http://www.switchonthecode.com/tutorials/wpf-printing-part-2-pagination . FormattedText apparaît ici.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X