rbulph Posted December 8, 2006 Posted December 8, 2006 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 Quote
Leaders snarfblam Posted December 8, 2006 Leaders Posted December 8, 2006 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? Quote [sIGPIC]e[/sIGPIC]
rbulph Posted December 8, 2006 Author Posted December 8, 2006 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. Quote
Leaders snarfblam Posted December 9, 2006 Leaders Posted December 9, 2006 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 Quote [sIGPIC]e[/sIGPIC]
rbulph Posted December 10, 2006 Author Posted December 10, 2006 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. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.