Solved

Detect if all text in TextBox is visible

Posted on 2006-06-09
8
656 Views
Last Modified: 2012-06-21
Wish to change the background color of a TextBox if the text is not all displayed.
Wish this to work with Multiline True or False, as well as for different client rectangle sizes, and different font sizes and bold/italic etc.

Purpose is to let user know that there is more text than is shown.

Tried this solution, but it is not exact.

' Control inherits from TextBox
Protected Overrides Sub OnTextChanged (ByVal e as System.EventArgs)
   MyBase.OnTextChanged(e)
   ' If it all fits, then background color is Window, else Control
   Dim clientWidth as Integer = ClientSize.Width
   Dim clientHeight as Integer = ClientSize.height
   Dim grfx as Graphics = CreateGraphics
   Dim fudgeWidth as Double = grfx.MeasureString(" X", Font, Integer.MaxValue)
   Dim actualSizeF as SizeF = grfx.MeasureString(Text, Font, clientWidth + fudgeWidth)

    If actualSizef.Height <= clientHeight then
        BackColor = Drawing.SystemColors.Window
    Else
        BackColor = Drawing.SystemColors.Control
    End If

    grfx.Dispose
End Sub      
   
' This works most of the time, but would like it to work all the time.
' Does TextBox use vanilla DrawString, or does it use some proprietary method of drawing text?
' Alternative is to build my own TextBox from scratch, but that doesn't sound pleasant!

Thank you,
Brother Bill
0
Comment
Question by:brotherbill999
8 Comments
 
LVL 28

Expert Comment

by:strickdd
ID: 16870651
In a multiline textbox you won't have to worry about "letting the user know" because it will display scroll bars. As for a single-line textbox the is no EXACT way to do this because all browsers interpret the textbox "columns" property slightly differently. The best thing to do would be to do a textbox.Text.Length and see if it is greater than the column numbers, that will typically mean there is more text, but not always.
0
 

Author Comment

by:brotherbill999
ID: 16871216
Clarification: This is a Winforms TextBox, not ASP.NET.
A single line textbox may have an overflow of data, without visually indicating so.
A multi-line textbox may not have scroll bars, therefore the user may not be aware of additional data.

Thus, the reason for the question.  It would be nice to provide a background color difference if some data is hidden.
0
 
LVL 5

Expert Comment

by:AdGroot
ID: 16872031
Try this

          if (textBox1.PreferredSize.Width > textBox1.Size.Width)
            {
                textBox1.BackColor = Color.Red;
            }
            else
            {
                textBox1.BackColor = Color.Blue;
            }
 

Ad
0
DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

 

Author Comment

by:brotherbill999
ID: 16872695
Hi AdGroot.  
Your solution is *close* for Multiline = False, but it displays overflow color, even when text fits.
Your solution doesn't work at all for MultiLine=True.

Would appreciate other suggestions...
Brother Bill
0
 
LVL 2

Accepted Solution

by:
shy_talk earned 500 total points
ID: 16873308
Just to add to the confusion...

I got this working after a fashion. Dont' gush with gratitude. The code is crap,  but it worked OK at first glance with single line textbox and another invisible textbox of the same size on the same form. I know for a fact that this will not work as it is with multiline, but who knows, a genius like yourself may well be able to succeed where a sucker like me has failed. Good luck.

   private void textBox3_TextChanged(object sender, EventArgs e)
      {
         
         TextBox txt = (TextBox)sender;
       
  // Just bulletproofing
         if (textBox4.Size != txt.Size)
         {
            textBox4.Size = txt.Size;
         }

// Copy the text to the invisible TextBox
         textBox4.Text = txt.Text;
         Application.DoEvents();

// Sample the index at the left of the box
         textBox4.SelectionStart = 0;  
         c1 = textBox4.GetCharIndexFromPosition(new Point(2, 2));

// Try to scroll the box
         textBox4.SelectionStart = txt.Text.Length;   //textBox4.Text.Length;
         c2 = textBox4.GetCharIndexFromPosition(new Point(2, 2));
       
// Well, here goes sod all...
         if (c1 != c2)
         {
            txt.BackColor = Color.Pink;
         }
         else
         {
            txt.BackColor = Color.White;
         }
      }

// You did ask for suggestions, not solutions...
0
 

Author Comment

by:brotherbill999
ID: 16875056
Great job shy_talk.  Just streamlined your solution, and figured out the Multi-line solution.  Just count the lines used, vs. available lines.  Anyway, here is the documented source code.  Thank you all.
Thus, the user can be informed, via background color, that there is hidden text in a TextBox.



    ' Inherited from TextBox, so Me is a TextBox
    Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
        MyBase.OnTextChanged(e)
        ' If it all fits, then background color is Window, else Control
        If FullyVisible(Me) Then
            BackColor = Drawing.SystemColors.Window
        Else
            BackColor = Drawing.SystemColors.Control
        End If
    End Sub

    ' This is the work horse...
    Public Function FullyVisible(ByVal txtBox As TextBox) As Boolean
        If txtBox Is Nothing Then Throw New ArgumentException("FullyVisible: txtBox may not be Nothing")
        Dim Result As Boolean
        If txtBox.Text.Length = 0 Then
            ' No matter how small the textbox is, you see all that there is, that is Nothing
            Result = True
        ElseIf txtBox.Multiline = False Then
            ' Create a copy of original text box, and copy key attributes
            Dim txtBox2 As New TextBox
            Dim pt2_2 As New Point(2, 2)
            txtBox2.Font = txtBox.Font
            txtBox2.Size = txtBox.Size
            txtBox2.Text = txtBox.Text
            ' c1 is char index 2 pixels from left, typically 0
            txtBox2.SelectionStart = 0
            Dim c1 As Integer = txtBox2.GetCharIndexFromPosition(pt2_2)
            ' c2 is char index 2 pixels from left, after scrolling to make last character visible
            txtBox2.SelectionStart = txtBox2.Text.Length
            Dim c2 As Integer = txtBox2.GetCharIndexFromPosition(pt2_2)
            ' If character indexes are equal, then you see all there is to see
            Result = (c1 = c2)
        Else
            ' MultiLine = True
            ' Client Height is the maximum vertical area inside the box where text may be written, excluding margins
            Dim clientHeight As Integer = txtBox.ClientSize.Height
            ' Line Height is number of pixels for each row, including white space
            Dim lineHeight As Integer = Math.Ceiling(txtBox.Font.GetHeight)
            ' Max Lines is number of visible lines of text
            Dim maxLines = Math.Floor(clientHeight / lineHeight)  ' Maximum rows that can be shown

            Dim len = txtBox.Text.Length
            ' Find which line (origin 1) that the last character is on
            Dim line1 As Integer = 1 + IIf(len = 0, 0, Me.GetLineFromCharIndex(len))
            ' If its within the max lines, its fully visible, else there is some hidden text
            Result = (line1 <= maxLines)
        End If

        Return Result
    End Function
0
 
LVL 2

Expert Comment

by:shy_talk
ID: 16882148
Well, what a pleasant surprise! Two heads and all that. Great little puzzle. Thanks for the points, bro'.
0
 

Author Comment

by:brotherbill999
ID: 16884895
When making the project Option Strict, noticed that certain variables need to be cleaned up, such as maxLines and len.  I'll post that at a later time.
0

Featured Post

Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Recently while returning home from work my wife (another .NET developer) was murmuring something. On further poking she said that she has been assigned a task where she has to serialize and deserialize objects and she is afraid of serialization. Wha…
In my previous two articles we discussed Binary Serialization (http://www.experts-exchange.com/A_4362.html) and XML Serialization (http://www.experts-exchange.com/A_4425.html). In this article we will try to know more about SOAP (Simple Object Acces…
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…
In an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…

839 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question