Limit Text in Text Area

I have a notes text area that later can be printed by the user onto its own page.

How do I limit the number of lines or characters in the text area box?
and/or indicate to the user they have reached a limit?

My print routine will print the notes up to the last line on the page.
Anything other than that is not printed. But it would be user friendly
to let them know when they enter the text that they are over the limit.

Counting characters does not work because of line returns. My print
routine uses Shorts which let’s you set the height of the text block before printing.

http://documentation.xojo.com/index.php/TextArea.LimitText

That’s cool but if they use a bunch of carriage returns… the number of chars may fit but it doesn’t fit the printed page.

I can just set this limit as a precaution but I don’t think it aligns with printing “one page of notes” which would related to the available printer area minus header and footer as well as font size.

use KeyDown

if CountFields(me.Text, EndOfLine) > 5 then // 5 Lines return true end if

[quote=314908:@Axel Schneider]use KeyDown

if CountFields(me.Text, EndOfLine) > 5 then // 5 Lines return true end if[/quote]
That won’t work if you have a single paragraph that wraps to 5 lines.

Use Graphics.StringHeight to get the height of the text for the width you will be printing it.

But, why limit in the first place? Why not allow the notes to print to however many pages it requires?

If I write my print routine to allow these notes to keep going to more pages if the text exceeds the page… then I could probably not worry about it but I was trying to keep the notes page to one single page. It’s not meant to put a “document” into the report but just a few quick notes.

Right now I have used Text limit to limit the characters and then used the amount of print are to limit what’s printed.

The problem with this approach is that depending on the number of carriage returns, the printer, how much is in all caps, etc. they may not hit the limit on the text area but the text wont fit on one page. I just didn’t think that was “user friendly”.

What if your user deliberately want to have some pages of notes ?

Alternate thinking:
What if you simply add a foot note that is: “Read Note # 5 in the Notes Appendix” for far larger notes ?

The idea is to let the user be productive… as productive as (s)he want to be !

If the rule is clearly stated, they know that pressing an inordinate number of return will just get to the limit.

Another way would be to suppress more than one return in a row.

Something like this in TextChange should do it :

dim oldSelStart as me.SelStart me.Text = ReplaceAll(chr(10)+chr(10), chr(10)) me.selstart = oldSelStart

Saving and putting back SelStart after replace is needed to prevent the caret to jump.

If I am not mistaken, chr(10) is the return character within a TextArea now for all platforms. In case it did not work as expected, try chr(13), or EndOfLine.

[quote=314930:@Tim Turner]If I write my print routine to allow these notes to keep going to more pages if the text exceeds the page… then I could probably not worry about it but I was trying to keep the notes page to one single page. It’s not meant to put a “document” into the report but just a few quick notes.

Right now I have used Text limit to limit the characters and then used the amount of print are to limit what’s printed.

The problem with this approach is that depending on the number of carriage returns, the printer, how much is in all caps, etc. they may not hit the limit on the text area but the text wont fit on one page. I just didn’t think that was “user friendly”.[/quote]
Don’t use the character limit at all, use the Graphics.StringHeight to calculate the height of the text entered, and compare that to the available space.

Using the character limit, as you said, is inaccurate as different characters are different widths, and there’s no way to factor carriage returns into the limit.

I had a drastic example of a similar discussion over a job a while ago with a client, where the designer of a form only had left room for only a single line of copy for ‘Additional Notes’. And this was a medical form, where the user should definitely be allowed to enter whatever is necessary for this condition. The client and account people were told by their IT that they could put a character limit on the database field; they wouldn’t listen to me telling them that A) a character limit was useless as it didn’t work effectively (if you made it small enough to account for wide letters, you’re limiting it too much for normal width letters, and vice versa), B) The character limit could easily be rendered useless by typing a few words and a carriage return, and C) The people using this form needed to be able to use whatever language was necessary to describe the condition accurately, and shouldn’t be limited by the space available to keep the form on a single page. Form should follow function.

Your comment is very valid for most situations. For my app though the user just wants a few quick notes. It’s not for writing up long series. I just thought I would make it more bullet proof by actually checking or limiting or conforming them to not exceed the bounds that I set in place. I was trying to “keep it simple”. If I allow more than one page I have to add more code, update page numbering, etc. I was just trying to limit it to one page and call it a day but it is possible that “limiting it” might be harder than just “printing as many notes pages as they want”.

Try something like this (untested, can be optimized) to find the part of a string that fits:

Function (mystring as String, width as Integer, height as Integer, font as String, fontsize as Integer) as String
  // Returns the beginning part of teststring that fits into a rectangular area, using given font and fontsize

  dim pict as Picture
  pict = New Picture(1,1) // just to obtain a test graphics object; size shouldn't matter
  pict.Graphics.TextFont = font
  pict.Graphics.TextSize = fontsize

  dim limit as Integer = Len(mystring) + 1 // start with one too many since the loop immediately subtracts 1

  do until limit = 0
    limit = limit - 1 // make the string shorter and shorter
  loop until pict.Graphics.StringHeight(Mid(mystring, 1, limit), width) <= height

  Return Mid(mystring, 1, limit) // return the part that fits
End Function

OK when I get a chance I will try this. Thanks.

How do I determine the width and height available?

Is it in “points”? How does resolution impact it?

Thanks.

I just noticed that in my year-old post I didn’t give the function a name. I’m sure you figured that out.

Typically you would use the values from the PrinterSetup as specified in PageSetupDialog, which are in pixels. If you are using Briefs, check the documentation. I have never used it.

The supplied width and height must be in the same unit system as the fontsize (pixels in the classic Framework, I don’t know about the new framework). Resolution will affect width and height, and fontsize in the same way.