Link to home
Start Free TrialLog in
Avatar of CodeWizrd
CodeWizrd

asked on

Column limit in multiline text entry


This may seem like an easy question, but it's been a real pain in my tookus.

I have an application, which has on one form, a multi-line text box.  My problem is a little complicated, yet fairly straight forward.

I need to be able to set a limit on how many characters can be on a line (80 characters, for example).  I am already using a fixed font, so the text is uniform in this respect.

I have tried using the RTF control, with it's ability to word-wrap.  The problem I have it that when it DOES a wordwrap, it does not insert a CRLF into the string where that wrap occurs.

I need to, when editing is finished, be able to read through the box and pull out the lines to be written to a target interface.

I need to be able to do this, with a CRLF being injected when the wordwrap occurs.

Do I need a Third Party control?

Also, the fixedsystem font is working well, but I need a smaller fontsize.  Anyone know of a smaller, fixed font?  How difficult is it to distribute and register this additional font with an application?  (Never done that before)

Thanks!

Avatar of VK
VK
Flag of Germany image

Hello CodeWizrd !

Suggestion:

1. Your multiline Textbox: txtMultiline
2. Your Label: lblOneLine
    a. lblOneLine.Font = txtMultiline.Font
    b. lblOneLine.Autosize=true
    c. lblOneLine.Visible=false
3. A Varaible tmpLine As String

4. After you begin a new line or begin the first line:
   tmpLine=""

5. txtMultiline_change:
   tmpLine= mid(txtMultiline,LastPosLineFeed+1)
   lblOneLine.Text=tmpLine
   if lblOneLine.width >= txtMultiline.width then
     ....
   end if

You understand ?

v.k.
P.S:

Sorry lblOneLine.Text has to be lblOneLine.caption.
But the principle isn't affected.

v.k.
Avatar of CodeWizrd
CodeWizrd

ASKER


Vk,

I thought about trying to track what is happening through the _change() event, but what happens with CUT and PASTE, or if the user inserts text in the middle of existing text?

What I could really use, is something like the ability of knowing exactly what column I was on in the current line (kinda kludgy, but I could write a buncha code to make it work) or that some sort of wordwrap that I would know a line was wordwrapped when I go to save the file.

See, the user has the ability to modify the look and feel, add and delete lines as well as blank lines for spacing and such.  What Im looking for is a way to take EXACTLY what they see on the screen and break it into individual lines.

I can do this right now with a multi-line text box, only I cannot stop the users from going more than "n" columsn, which I need.

HELP?!
I would recommend using a different control to handle this.  Since each line represents a different entity, they should either be in one control for each line (multiple textboxes) or something like a grid.

If you use the textbox idea, there will obviously be issues with navigation between the lines.

With a grid, you could handle all of the editing through the keydown/up events.  Then, for dataentry, just allow users to enter up to 80 characters in a cell.

There may be additional issues since the MSFlexGrid was not really designed for data input.

The other choice, as mentioned, is to put all checks within the multi-line textbox, but this can be a nightmare if you start allowing user deletions and insertions, especially if done by pasting information.
<I need to, when editing is finished>  How will you know when editing is finished?  I assume that means that when the user presses a button or otherwise indicates that editing is finished.  In any case, you could insert the CRLFs yourself whether it's on the Change event or on a button.

Using the split function you can drop the lines into an array (I just love that split function).  Then cycle through the array one line at a time
If the line is less than 80 characters long, append it to a local string with a VBCRLF on the end.
If the line is > 80 characters, take the first 80 characters, append a vbcrlf, the next 80 append crlf, etc in a looping structure). and append it to your string.  When you are finished, put the local string back into the textbox.

If course this is a lot of overhead for the Change event, so maybe you do it when the user says "Done" by pressing a button.


CodeWizrd,

See this. Create a new Project with Form1, Text1(0), Text1(1) and Text1(1).Width remarkable wider than Text1(0).Witdh. Because

Private Function vbNewLineDelimitedStr(ByVal txtBox As TextBox) As String
    Static L As Integer
    Static R As Integer
    Static T As Integer
    Static i As Integer
    Dim Result As String
       
    T = Len(txtBox.Text)
   
    L = 1
   
    For i = 1 To T
        R = 1 + i - L
        lblTemp.Caption = Mid(txtBox.Text, L, R)
        If lblTemp.Width >= txtBox.Width Then
            Result = Result & Mid(txtBox.Text, L, R - 1) & vbNewLine
            L = i
            R = 1 + i - L
            lblTemp.Caption = Mid(txtBox.Text, L, R)
        End If
    Next
   
    If L < i Then
            Result = Result & Mid(txtBox.Text, L)
    End If
    vbNewLineDelimitedStr = Result
   
End Function

Private Sub Form_Load()
    Set lblTemp.Font = Text1(0).Font
    lblTemp.AutoSize = True
    lblTemp.Visible = False
End Sub

Private Sub Text1_Change(Index As Integer)

    Text1(1).Text = vbNewLineDelimitedStr(Text1(0))
End Sub
Sorry got the wrong key .. and my browser send it unfinished :-)

.. because Text1_Change(0) is fired even if you insert or remove text with CTRL+ this should work:

v.k.
Of Course, i forgot to tell that a label lblTemp has to placed on the form.
Design TextBox.ScrollBars = 2 - Vertical, and Size TextBox.Width just fit 80 char, so TextBox have a autowarp behavior when use input.
when editing is finished, use WarpText(TextBox.Text, 80) function to get a True warped text.

Function WarpText(ByVal text As String, ByVal LineWidth As Long) As String
    Dim saLines() As String
    Dim I As Long
    Dim sLine As String
   
    If text <> vbNullString Then
        saLines = Split(text, vbCrLf)
        For I = 0 To UBound(saLines)
            sLine = saLines(I)
           
            Do
                WarpText = WarpText & Left(sLine, LineWidth) & vbCrLf
                sLine = Mid(sLine, LineWidth + 1)
            Loop While sLine <> vbNullString
        Next
    End If
End Function
Typo
  "behavior when use input"
=>
  "behavior when user input"
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in Community Support that this question is:
- Split points between TigerZhao and VK
Please leave any comments here within the
next seven days.

I actually never got my question answered adequately, so I built a user control to do the job for me.  I tried the solutions that were posted, but none of them covered all of the bases.

Im fine with splitting the points, since you guys did try to answer it.  How would I go about doing so?  Dont think I have the option..
CodeWizrd,
If you did not use any of the suggestions here in building your usercontrol, then you are entitled to a full refund of the points.  If you did however, you should let us know whose code you chose.

twalgrave,

I subclassed the RTF control, and when wordwrapping occurred, I treated it as if the user hit return, so it put a crlf into the box at that point.  I also kept a reference of the CRLFs that I put in, so if editing caused things to change, I could readjust the CRLFs as needed.

I bundled all of this functionality into a user control for easy usage in my application.

Its kind of messy, but it was the only way to achieve exactly what I needed.
I'd say that a refund is in order.  Post a zero-point question in Community support titled please refund and close, then add the URL to this question into the comment area.  They will decide what to do.

https://www.experts-exchange.com/questions/20401260/Column-limit-in-multiline-text-entry.html
ASKER CERTIFIED SOLUTION
Avatar of Computer101
Computer101
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial