Skip navigation

Monthly Archives: February 2008

I recently had to use a combobox with the flat style. I really dont like to do it because it renders flat, but without a border. It seems that this control is not a .net instrinsic control, but rather a wrapper around the combobox used within Windows itself. Because of this, it seems quite difficult to owner draw a solution. I have seen a few solutions with lots of code, but even those didnt work flawlessly for me. I even went as far as putting my own code in the paint event, and maually drawing a border around the rectangle of the control, but I was unahppy with the results. Because its not a .net control, it’s just not flexable enough for me. I know I’m picky, but I like my controls like my women, flexable <grin>. So I put up with the borderless thing.

When using the combobox with the flatstyle set to flat and anchoring the combobox to grow with a form, the combobox has trouble rendering. You often get the following:

 badcombo.png

As you can see, the combo renders the flatstyle properly the first time, but after the anchor stretches the combobox, the rendering gets all jacked up. This seems to be a bug in the way the control works with the underlying combobox control from Windows itself.

If you need a workaround, I found the following to work well. It’s not a bug fix, but it does work, and thats what I am all about.

Hook up a Resize event and put the following in it:

private void _cboMyCombo_Resize(object sender, EventArgs e)
{
     _cboMyCombo.Refresh();
}

Enjoy!

-Jeff
blog:www.savij.com

Background 

I while back I created a control that inherited from a textbox. The requirements were that I needed to keep a new line below the currently typed text and that the control should not only grow in height as the rows wrapped, but that it should also push down any controls that were below the textbox on the form, as well as to grow the form as the user typed. What I came up with was the following. It has been a while since I used this code, but I quickly tested it and it seems to work, just put the textbox in multiline mode and drop it on a form and type away!!

Just wanted to share. Enjoy!

-Jeff
blog: www.savij.com

”’ <summary>
”’ This textbox will auto adjust it’s height with multi-line and wordwrap on.
”’ </summary>
”’ <remarks>After the parent form or control is Initialized, it MUST call Init()
”’ on this control. If not, the incorrect Parent.Height could get set and that
”’ will cause unexpected results.
”’ </remarks>
Public Class AutoHeightTextBox
Inherits TextBox

Private m_strHeight As Single = 0
Private m_txtHeightStart As Single = 0
Private m_ControlHeightStart As Single = 0
Private m_HeightofOneChar As Single = 0
Private m_LastHeightofTextbox As Single = 0
Private m_CollisionBuffer As Integer = 6

”’ <summary>
”’ Constructor
”’ </summary>
”’ <remarks></remarks>
Public Sub New()
MyBase.New()

m_txtHeightStart = Me.Height
m_LastHeightofTextbox = Me.Height
m_strHeight = Me.Height
End Sub

”’ <summary>
”’ The amount of space to pad when checking for a collision.
”’ </summary>
”’ <value>vale As Integer (pixels)</value>
”’ <returns></returns>
”’ <remarks>When the textbox increases in size, it will check to see if it is in
”’ danger of a collision with control drawn below it. It will add this buffer amount to
”’ it’s calculations. Setting this property to 0 will cause the textbox to touch the
”’ control below it before that control will get moved.
”’ </remarks>
Public Property CollisionBuffer() As Integer
Get
Return m_CollisionBuffer
End Get
Set(ByVal value As Integer)
m_CollisionBuffer = value
End Set
End Property

”’ <summary>
”’ Call this method after the parent has called it’s Initialize() method. This will read the
”’ actual parent.Height and set the value in this control.
”’ </summary>
”’ <remarks></remarks>
Public Sub Init()
m_ControlHeightStart = Parent.Height
End Sub

Private Sub AutoHeightTextBox_ParentChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.ParentChanged
If Parent Is Nothing Then Exit Sub

m_ControlHeightStart = Parent.Height
End Sub

Private Sub AutoHeightTextBox_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.TextChanged
Try
Me.SuspendLayout()
Dim iStringHeight As Single = 0
‘ Get a graphics object from the textbox
Using g As Graphics = Graphics.FromHwnd(Me.Handle)

Dim sf As New StringFormat(StringFormat.GenericTypographic)
‘ Create a rectangle equal to the size of the autowrap textbox
Dim oRect As Rectangle = Me.Bounds
g.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias
sf.FormatFlags = StringFormatFlags.NoClip
‘ Estimate the height of one char
m_HeightofOneChar = g.MeasureString(“W”, Me.Font).Height
‘ Get the estimate of the height of the current textbox.
iStringHeight = g.MeasureString(Me.Text, Me.Font, oRect.Width, sf).Height

End Using
‘ The height is wrong sometimes. It doesnt update upon wrap as it should, so we add a
‘ buffer to the bottom of the textbox.
iStringHeight += (Me.Font.Height * 2)

‘ Check if the measured string height is greater than the previous string height.
If iStringHeight > m_strHeight Then

‘ Increase the height of the textbox to that of the measurement (plus our buffer)
Me.Height = iStringHeight

‘ Since the height of the textbox has increased, check if we are in danger of a
‘ collision with another control below it on the parent.
If CheckCollision() Then
‘ We have a collision, so increase the parent height to accomodate the larger
‘ textbox size.
Parent.Height += (Me.Height – m_LastHeightofTextbox)
‘ Move any controls below me down.
MoveParentControlsDown(Me.Height – m_LastHeightofTextbox)
End If

‘Update tracking variables.
m_LastHeightofTextbox = Me.Height
m_strHeight = iStringHeight

Exit Sub
End If

‘ Check if the measured string height is less than the previous string height.
If iStringHeight < m_strHeight Then

‘ Decrease the height of the textbox to that of the measurement (plus our buffer)
Me.Height = iStringHeight

‘ Check if the Textbox height is less than the previous Textbox height. This
‘ would mean that the Textbox has decreased it’s height.
If m_LastHeightofTextbox > Height Then
‘ Move other controls up that are below me
MoveParentControlsUp(m_LastHeightofTextbox – Me.Height)
‘ Decrease the parent height to take up the space left my the Textbox resize.
Parent.Height -= (m_LastHeightofTextbox – Me.Height)
End If

‘Update tracking variables.
m_LastHeightofTextbox = Me.Height
m_strHeight = iStringHeight
Exit Sub
End If

Catch ex As Exception

Finally
Me.ResumeLayout()
End Try
End Sub

Private Function CheckCollision() As Boolean
Try
For Each oControl As Control In Parent.Controls
If (Location.Y + Height + 6) >= oControl.Location.Y AndAlso (oControl.Location.Y + oControl.Height) > (Location.Y + Height + 6) Then
Return True
End If
Next

‘Check for control border collision
If Location.Y + Height >= Parent.Height Then
Return True
End If

Return False
Catch ex As Exception

End Try
End Function

Private Sub MoveParentControlsDown(ByVal AmountToMove As Single)
Try

For Each oControl As Control In Parent.Controls
If Not oControl.Equals(Me) Then
If oControl.Location.Y > Location.Y Then
‘ Move the control down
oControl.Location = New Point(oControl.Location.X, oControl.Location.Y + AmountToMove)
End If
End If
Next

Catch ex As Exception

End Try
End Sub

Private Sub MoveParentControlsUp(ByVal AmountToMove As Single)
Try

For Each oControl As Control In Parent.Controls
If Not oControl.Equals(Me) Then
If oControl.Location.Y > Location.Y Then

oControl.Location = New Point(oControl.Location.X, oControl.Location.Y – AmountToMove)

End If
End If
Next

Catch ex As Exception

End Try
End Sub

End Class

Follow

Get every new post delivered to your Inbox.