Word Wrap while Printing

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jeff B.

    Word Wrap while Printing

    Has anyone come across a decent algorithm for implementing word wrap
    features in .net printing? I have a small component that uses basic
    printing techniques (i.e. e.Graphics.Draw String in a PrintPage event of a
    PrintDocument object) to send some formatted text to the printer. However,
    if the lines are too long they run off the page rather than wrapping around.
    I'm sure I can spend the time and come up with a word wrapping algorithm but
    figured why go through the trouble if someone already knows of one :-)

    --- Thanks, Jeff

    --

    Jeff Bramwell
    Digerati Technologies, LLC


    Manage Multiple Network Configurations with Select-a-Net



  • Kevin Yu [MSFT]

    #2
    RE: Word Wrap while Printing

    Hi Jeff,

    First of all, I would like to confirm my understanding of your issue. From
    your description, I understand that you need to print text with word wrap.
    If there is any misunderstandin g, please feel free to let me know.

    As far as I know, if you're trying to print RTF text, you can either use
    the old VB6 control and wrap it for .net, or you can write your own code.
    You can also use MS Word Automation and copy the RichText to a Word object
    and call its print method if you have Word. The latter is the lamest
    approach, but it works.

    Also, there are some 3rd party .NET components. Please try to check the
    following link:



    Kevin Yu
    =======
    "This posting is provided "AS IS" with no warranties, and confers no
    rights."

    Comment

    • Kevin Yu [MSFT]

      #3
      RE: Word Wrap while Printing

      Hi Jeff,

      If you use a drawstring that takes a rectanglef it will word wrap for you.

      g.DrawString(te xtbox1.text, textbox1.font, Brushes.Black,
      RectangleF.op_I mplicit(e.PageB ounds))

      Kevin Yu
      =======
      "This posting is provided "AS IS" with no warranties, and confers no
      rights."

      Comment

      • Picho

        #4
        Re: Word Wrap while Printing

        Jeff,

        When working with the Graphics.DrawSt ring method, one of the parameters is a
        StringFormat object. this object defines wrapping behaviour among other
        things.
        pass the StringFormat object definitions and a Rectangle object to draw on
        (rather than a Point) as parameters to the Graphics.DrawSt ring method and
        it should do the trick.

        I do that all the time - unless I misunderstood you.

        Picho


        "Jeff B." <jsb@community. nospam> wrote in message
        news:OWA0Te9EFH A.560@TK2MSFTNG P15.phx.gbl...[color=blue]
        > Has anyone come across a decent algorithm for implementing word wrap
        > features in .net printing? I have a small component that uses basic
        > printing techniques (i.e. e.Graphics.Draw String in a PrintPage event of a
        > PrintDocument object) to send some formatted text to the printer.
        > However, if the lines are too long they run off the page rather than
        > wrapping around. I'm sure I can spend the time and come up with a word
        > wrapping algorithm but figured why go through the trouble if someone
        > already knows of one :-)
        >
        > --- Thanks, Jeff
        >
        > --
        >
        > Jeff Bramwell
        > Digerati Technologies, LLC
        > www.digeratitech.com
        >
        > Manage Multiple Network Configurations with Select-a-Net
        > www.select-a-net.com
        >
        >[/color]


        Comment

        • Jeff B.

          #5
          Re: Word Wrap while Printing

          Thanks Kevin and Picho for the info. You both understood exactly what I was
          after and the "rectangle" method you mention almost does exactly what I
          need. The only part I'm missing is being able to increment the line count
          by how many lines the text was wrapped so the subsequent lines display
          correctly and the pages break correctly.

          I think I'm going to take a slightly different approach and break the lines
          out programmaticall y as I print them. I'll post back any successes - or
          failures :-)

          --- Jeff

          --

          Jeff Bramwell
          Digerati Technologies, LLC


          Manage Multiple Network Configurations with Select-a-Net


          "Jeff B." <jsb@community. nospam> wrote in message
          news:OWA0Te9EFH A.560@TK2MSFTNG P15.phx.gbl...[color=blue]
          > Has anyone come across a decent algorithm for implementing word wrap
          > features in .net printing? I have a small component that uses basic
          > printing techniques (i.e. e.Graphics.Draw String in a PrintPage event of a
          > PrintDocument object) to send some formatted text to the printer.
          > However, if the lines are too long they run off the page rather than
          > wrapping around. I'm sure I can spend the time and come up with a word
          > wrapping algorithm but figured why go through the trouble if someone
          > already knows of one :-)
          >
          > --- Thanks, Jeff
          >
          > --
          >
          > Jeff Bramwell
          > Digerati Technologies, LLC
          > www.digeratitech.com
          >
          > Manage Multiple Network Configurations with Select-a-Net
          > www.select-a-net.com
          >
          >[/color]


          Comment

          • Kevin Yu [MSFT]

            #6
            Re: Word Wrap while Printing

            Hi Jeff,

            Thanks for sharing your experience with all the people here. If you have
            any questions, please feel free to post them in the community.

            Kevin Yu
            =======
            "This posting is provided "AS IS" with no warranties, and confers no
            rights."

            Comment

            • Jeff B.

              #7
              Re: Word Wrap while Printing

              > I think I'm going to take a slightly different approach and break the[color=blue]
              > lines out programmaticall y as I print them. I'll post back any
              > successes - or failures :-)[/color]

              Just a follow up...

              I ended up creating a method that takes a line of text and returns an
              ArrayList of lines after performing a "word wrap" on them. This method lets
              me easily, and programatically , print lines while keeping track of how many
              lines have been printed - even if they've been "wrapped". Below is the code
              to the method I've created. I'm sure it can still be optimized somewhat and
              some things can probably be done more efficiently, so if anyone has any
              suggestions, please let me know. Please don't pay too much attention to the
              formatting, I've altered it somewhat so it takes up less space.

              <<< BEGIN CODE SNIPPET >>>
              private System.Collecti ons.ArrayList wordWrap(string text,
              System.Drawing. Font printFont, System.Drawing. Graphics graphics,
              System.Drawing. Rectangle marginBounds)
              {
              System.Collecti ons.ArrayList lines;
              string buffer = text;
              System.Drawing. SizeF size;
              int index1;
              int index2;
              char[] whitespace = new char[] {' ', '\t', '\r', '\n'};

              try {
              lines = new ArrayList();

              while (buffer.Length > 0) {
              size = graphics.Measur eString(buffer, printFont);

              if (size.Width > marginBounds.Wi dth) {
              // Find the wrapping point of the line based on the width
              for (index1 = buffer.Length - 1; index1 >= 0; index1--) {
              size = graphics.Measur eString(buffer. Substring(0, index1),
              printFont);

              if (size.Width <= marginBounds.Wi dth) {
              // We found the wrapping point now let's look for the first
              // whitespace character - if there is one
              index2 = buffer.LastInde xOfAny(whitespa ce, index1);

              if (index2 >= 0) {
              // Whitespace character found
              lines.Add(buffe r.Substring(0, index2));
              buffer = buffer.Substrin g(index2);
              break;
              }
              else {
              // Whitespace was not found
              lines.Add(buffe r.Substring(0, index1));
              buffer = buffer.Substrin g(index1);
              }
              break;
              }
              }
              }
              else {
              // This line completely fits so add it to the buffer unaltered
              lines.Add(buffe r);
              buffer = "";
              }
              }
              return lines;
              }
              catch {
              return null;
              }
              finally {
              lines = null;
              }
              }
              <<< END CODE SNIPPIET >>>

              --

              Jeff Bramwell
              Digerati Technologies, LLC


              Manage Multiple Network Configurations with Select-a-Net



              Comment

              • Ron Allen

                #8
                Re: Word Wrap while Printing

                Jeff,
                To get the # of lines used for the wrapped printing you can use the
                MeasureString method that takes a SizeF argument (#7 of 7 in my Intellisense
                list). The SizeF should be the width and height of the rectangle you are
                printing in and, of course, use the same StringFormat as the DrawString
                call. This overload has two out parameters nline, and nchars that return
                the # of lines and characters that fit. If nchars is less than the length
                of the string the string would be truncated on output. You can use this to
                see if remaining text fits on the rest of the page and then advance the
                baseline by the # of lines returned after you draw the string.

                Ron Allen
                "Jeff B." <jsb@community. nospam> wrote in message
                news:eEksTeJFFH A.2540@TK2MSFTN GP09.phx.gbl...[color=blue]
                > Thanks Kevin and Picho for the info. You both understood exactly what I
                > was after and the "rectangle" method you mention almost does exactly what
                > I need. The only part I'm missing is being able to increment the line
                > count by how many lines the text was wrapped so the subsequent lines
                > display correctly and the pages break correctly.
                >
                > I think I'm going to take a slightly different approach and break the
                > lines out programmaticall y as I print them. I'll post back any
                > successes - or failures :-)
                >
                > --- Jeff
                >
                > --
                >
                > Jeff Bramwell
                > Digerati Technologies, LLC
                > www.digeratitech.com
                >
                > Manage Multiple Network Configurations with Select-a-Net
                > www.select-a-net.com
                >
                > "Jeff B." <jsb@community. nospam> wrote in message
                > news:OWA0Te9EFH A.560@TK2MSFTNG P15.phx.gbl...[color=green]
                >> Has anyone come across a decent algorithm for implementing word wrap
                >> features in .net printing? I have a small component that uses basic
                >> printing techniques (i.e. e.Graphics.Draw String in a PrintPage event of a
                >> PrintDocument object) to send some formatted text to the printer.
                >> However, if the lines are too long they run off the page rather than
                >> wrapping around. I'm sure I can spend the time and come up with a word
                >> wrapping algorithm but figured why go through the trouble if someone
                >> already knows of one :-)
                >>
                >> --- Thanks, Jeff
                >>
                >> --
                >>
                >> Jeff Bramwell
                >> Digerati Technologies, LLC
                >> www.digeratitech.com
                >>
                >> Manage Multiple Network Configurations with Select-a-Net
                >> www.select-a-net.com
                >>
                >>[/color]
                >
                >[/color]


                Comment

                • Jeff Louie

                  #9
                  Re: Word Wrap while Printing

                  Jeff B... Here is an attempt to break up text into an array of lines
                  that fit on a page.

                  ===== // UNTESTED // ======

                  public void ResetArray(IPri ntEngine pe,
                  Graphics g,
                  RectangleF clipRect)
                  {
                  arrayLines.Clea r();
                  float pageWidth= clipRect.Width- (this.horizonta lMargin*2);
                  char newLineChar= '\r';
                  char space= ' ';
                  // use tabAsString later to convert tabs to spaces
                  StringBuilder tabBuilder= new StringBuilder() ;
                  for(int i=0; i<this.tabSize ; i++)
                  {
                  tabBuilder.Appe nd(space);
                  }
                  string tabAsString= tabBuilder.ToSt ring();

                  // get properties and parse text
                  Brush brush;
                  Font font;
                  StringFormat stringFormat;
                  if (this.isUseDocu mentProperties)
                  {
                  brush= pe.Brush;
                  font= pe.Font;
                  stringFormat= pe.StringFormat ;
                  }
                  else
                  {
                  brush= new SolidBrush(Colo r.Black);
                  font= this.Font;
                  stringFormat= this.stringForm at;
                  }
                  string text= this.Text;
                  if (this.isReplace Tokens)
                  {
                  text= pe.ReplaceToken s(text);
                  }

                  // break out lines with embedded line break
                  string temp= this.Text.Repla ce(System.Envir onment.NewLine, "\r");
                  string[] arrayUnfittedLi nes= temp.Split(newL ineChar);

                  // break out lines that overflow
                  foreach (string line in arrayUnfittedLi nes)
                  {
                  // replace tabs with spaces
                  string parsed;
                  parsed= line.Replace("\ t",tabAsString) ;
                  // add to array if line of word tokens fits in page margin
                  if (g.MeasureStrin g(parsed,font,
                  Int32.MaxValue,
                  stringFormat).W idth <= pageWidth)
                  {
                  arrayLines.Add( parsed);
                  }
                  else
                  // line does not fit on page
                  // need to break up line into word tokens
                  // and then place tokens into lines that fit in page margin
                  {
                  string[] arrayTokens= parsed.Split(sp ace); // tokenize line
                  StringBuilder buffer;
                  int index=0;
                  while (index < arrayTokens.Len gth)
                  {
                  buffer= new StringBuilder() ;
                  // at least one token on line, ? may be clipped
                  buffer.Append(a rrayTokens[index]+space);
                  index++;
                  while(index< arrayTokens.Len gth &&
                  g.MeasureString (buffer.ToStrin g()+arrayTokens[index],
                  font,
                  Int32.MaxValue,
                  stringFormat).W idth <= pageWidth)
                  {
                  buffer.Append(a rrayTokens[index]+space);
                  index++;
                  }
                  // end of tokens or end of line
                  arrayLines.Add( buffer.ToString ());
                  }
                  }
                  }
                  this.currentInd ex= 0;
                  }
                  Regards,
                  Jeff[color=blue]
                  >I think I'm going to take a slightly different approach and break the[/color]
                  lines out programmaticall y as I print them. I'll post back any successes
                  - or failures :-)<



                  Regards,
                  Jeff
                  Has anyone come across a decent algorithm for implementing word wrap
                  features in .net printing?

                  *** Sent via Developersdex http://www.developersdex.com ***
                  Don't just participate in USENET...get rewarded for it!

                  Comment

                  • Jeff Louie

                    #10
                    Re: Word Wrap while Printing

                    I have had a chance to work on a word wrap alogrithm and it can be
                    improved by extracting the lines directly from the textbox:

                    string[] arrayUnfittedLi nes= new string[this.Lines.Leng th];
                    this.Lines.Copy To(arrayUnfitte dLines,0);

                    Secondly, there is no need to replace tabs, simply set the tab stops as
                    in:

                    stringFormat.Se tTabStops(0.0f, pe.TabStops);

                    Regards,
                    Jeff

                    *** Sent via Developersdex http://www.developersdex.com ***
                    Don't just participate in USENET...get rewarded for it!

                    Comment

                    • wschlichtman

                      #11
                      RE: Word Wrap while Printing

                      I see you've already found a fix to your issue but I thought others might
                      like a an answer to your original question. Here's what I do for wordwrap
                      using the tools supplied with .NET.

                      // This routine will print a document with 2 columns,
                      // wordraped text in each column, the left and right
                      // columns match row sizes, similare to equal cell sizes
                      private void document_PrintP age(object sender,
                      System.Drawing. Printing.PrintP ageEventArgs e)
                      {
                      float left = e.MarginBounds. Left;
                      float top = e.MarginBounds. Top;
                      float width = e.MarginBounds. Width / 2 - 5; // this spaces the columns
                      evenly
                      float height = e.MarginBounds. Height;
                      int fitted = 0; // use only to correctly format the MeasureString method
                      int qFilled = 0, aFilled;

                      // The variables are named to identify a question column and an answer
                      column
                      RectangleF qDrawRect = new RectangleF(left , top, width, height); // Left
                      column rectangle
                      RectangleF aDrawRect = new RectangleF(left + width + 10, top, width,
                      height); // right

                      // Setup to measure the line lines
                      SizeF qSizeF = new SizeF(width, height);
                      SizeF aSizeF = new SizeF(width, height);

                      // Although you can initialize string attributes here
                      // this line is only to fill in the parameter list
                      // We'll use whatever is given to us
                      StringFormat newStringFormat = new StringFormat();

                      // The following code sets the font to be
                      // the same as the displayed font (in this case, in
                      // a datagrid)
                      System.Drawing. Font printFont = new System.Drawing. Font
                      (myGrid.Default CellStyle.Font. Name,
                      myGrid.DefaultC ellStyle.Font.S ize,
                      myGrid.DefaultC ellStyle.Font.S tyle);

                      // Insert code to render the page here.
                      // This code will be called when the control is drawn.
                      while (linesPrinted <= lines.GetUpperB ound(0))
                      {
                      // Here's where we find out how many lines will be printed during a
                      word wrap
                      e.Graphics.Meas ureString(lines[linesPrinted,0], printFont,
                      qSizeF, newStringFormat , out fitted, out qFilled);
                      e.Graphics.Meas ureString(lines[linesPrinted,1], printFont,
                      aSizeF, newStringFormat , out fitted, out aFilled);

                      // This prints the two columns, properly formatted and,
                      // if necessary, wordwrapped
                      e.Graphics.Draw String(lines[linesPrinted, 0], printFont,
                      System.Drawing. Brushes.Black, qDrawRect);
                      e.Graphics.Draw String(lines[linesPrinted++, 1], printFont,
                      System.Drawing. Brushes.Black, aDrawRect);

                      // Now we use the info we gathered in the MeasureString statement
                      // If either column wrapped, qFilled and/or aFilled will be larger
                      than 1
                      // I'm using the ?: operator to determine which is larger and using
                      that
                      // one. I also add a half line to the equation to provide "paragraph"
                      // spacing, a nice touch to the printout
                      aDrawRect.Y += (int)myGrid.Def aultCellStyle.F ont.Height *
                      (qFilled > aFilled ? qFilled : aFilled) +
                      (int)(myGrid.De faultCellStyle. Font.Height * .5);
                      qDrawRect.Y = aDrawRect.Y;

                      if (aDrawRect.Y >= e.MarginBounds. Bottom)
                      {
                      e.HasMorePages = true;
                      return;
                      }
                      }
                      linesPrinted = 0;
                      e.HasMorePages = false;
                      }


                      "Jeff B." wrote:
                      [color=blue]
                      > Has anyone come across a decent algorithm for implementing word wrap
                      > features in .net printing? I have a small component that uses basic
                      > printing techniques (i.e. e.Graphics.Draw String in a PrintPage event of a
                      > PrintDocument object) to send some formatted text to the printer. However,
                      > if the lines are too long they run off the page rather than wrapping around.
                      > I'm sure I can spend the time and come up with a word wrapping algorithm but
                      > figured why go through the trouble if someone already knows of one :-)
                      >
                      > --- Thanks, Jeff
                      >
                      > --
                      >
                      > Jeff Bramwell
                      > Digerati Technologies, LLC
                      > www.digeratitech.com
                      >
                      > Manage Multiple Network Configurations with Select-a-Net
                      > www.select-a-net.com
                      >
                      >
                      >[/color]

                      Comment

                      Working...