Jump to content
Xtreme .Net Talk

Recommended Posts

Posted

I'd like to have an autosize textbox and combobox. While these controls do have a (hidden) AutoSize property, setting this property doesn't seem to have any impact. So I have come up with the following code, which you will appreciate is not perfect. Any suggestions for improvements, especially removal of the figure 6?

 

Public Class Form1

   Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged, ComboBox1.TextChanged

       With CType(sender, Control)
           Dim lbl As New Label
           Me.Controls.Add(lbl)
           lbl.Font = .Font
           lbl.AutoSize = True
           lbl.Text = .Text
           Dim W As Integer = lbl.Width
           If TypeOf sender Is ComboBox Then W = W + SystemInformation.VerticalScrollBarWidth + 6
           .Width = W
           lbl.Dispose()
       End With

   End Sub

End Class

  • Leaders
Posted

The AutoSize property is hidden because it is not implemented (hence, it does not work). There are many properties that are hidden because they aren't implemented or become irrelevant in a derived class.

 

Also, instead of creating a label to measure the size of a string, why not create a graphics object and use the MeasureString function to measure the string?

[sIGPIC]e[/sIGPIC]
Posted
Also' date=' instead of creating a label to measure the size of a string, why not create a graphics object and use the MeasureString function to measure the string?[/quote']

Because a label is a closer approximation to a textbox than a graphics object. A control, be it a label or a textbox, consists of more than just the space that its text contains. It has borders and spare space around the edges. If I use MeasureString I get a value about 2.5 pixels less for the width than if I create a label and measure its width, and using a label removes the potential uncertainty in the actual amount of this 2.5 pixels.

  • Leaders
Posted

Unfortunately, creating labels also requires much more resources than the graphics object, and it is not designed to do what you are using it for, which means that you may run into unexpected bugs and behavior might change in future versions. As far as taking borders into account, well, that's why we have the ClientRectangle property. We can compare ClientRectangle to Bounds and find the size difference, i.e. the border size.

 

Public Class AutosizeTextBox
   Inherits TextBox

   Dim _AutoSize As Boolean = True
   <System.ComponentModel.DefaultValue(True)> _
   Public Shadows Property AutoSize() As Boolean
       Get
           Return _AutoSize
       End Get
       Set(ByVal value As Boolean)
           _AutoSize = value
           If _AutoSize Then SizeControl()
       End Set
   End Property

   Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
       MyBase.OnTextChanged(e)

       If _AutoSize Then SizeControl()
   End Sub

   Sub SizeControl()
       'Use a graphics object to measure the text
       Dim g As Graphics = Me.CreateGraphics()

       'Measure the text
       Dim s As SizeF = g.MeasureString(Me.Text, Me.Font, 1000000)

       'Adjust for the border
       s.Width += Me.Width - Me.ClientRectangle.Width
       s.Height += Me.Height - Me.ClientRectangle.Height
       'Extra space for the caret
       s.Width += 3

       'Set the size
       Me.Size = s.ToSize

       'Hack: Because the box isnt resized until _after_
       'new text is typed, the text is scrolled to the left,
       'out of view. This code brings it back into view.
       Dim selection As Integer = SelectionStart
       SelectionStart = 0
       SelectionStart = selection

       'Dispose our IDisposables
       g.Dispose()
   End Sub

End Class

[sIGPIC]e[/sIGPIC]
Posted
Unfortunately, creating labels also requires much more resources than the graphics object, and it is not designed to do what you are using it for, which means that you may run into unexpected bugs and behavior might change in future versions. As far as taking borders into account, well, that's why we have the ClientRectangle property. We can compare ClientRectangle to Bounds and find the size difference, i.e. the border size.

 

Public Class AutosizeTextBox
   Inherits TextBox

   Dim _AutoSize As Boolean = True
   <System.ComponentModel.DefaultValue(True)> _
   Public Shadows Property AutoSize() As Boolean
       Get
           Return _AutoSize
       End Get
       Set(ByVal value As Boolean)
           _AutoSize = value
           If _AutoSize Then SizeControl()
       End Set
   End Property

   Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
       MyBase.OnTextChanged(e)

       If _AutoSize Then SizeControl()
   End Sub

   Sub SizeControl()
       'Use a graphics object to measure the text
       Dim g As Graphics = Me.CreateGraphics()

       'Measure the text
       Dim s As SizeF = g.MeasureString(Me.Text, Me.Font, 1000000)

       'Adjust for the border
       s.Width += Me.Width - Me.ClientRectangle.Width
       s.Height += Me.Height - Me.ClientRectangle.Height
       'Extra space for the caret
       s.Width += 3

       'Set the size
       Me.Size = s.ToSize

       'Hack: Because the box isnt resized until _after_
       'new text is typed, the text is scrolled to the left,
       'out of view. This code brings it back into view.
       Dim selection As Integer = SelectionStart
       SelectionStart = 0
       SelectionStart = selection

       'Dispose our IDisposables
       g.Dispose()
   End Sub

End Class

OK, I didn't realise that ClientRectangle existed for controls. Shame it just gives the control's Bounds for combo boxes though.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...