.NET Programming With Me

VB.NET : Adjusting ComboBox DropDownList width to longest string width

A ComboBox dropdown width defaults to the width of the control itself. When items in the list are longer than the control, they get clipped and the user cannot read them without selecting. Windows Forms does not resize the dropdown automatically, so you have to measure and set it yourself.

This comes up any time a ComboBox is sized to fit a form layout rather than its content, which is most of the time. A narrow control with long display values is one of those small usability issues that is easy to overlook and just as easy to fix.

The fix

The function below measures every item string using the control's own font and Graphics context, accounts for the vertical scrollbar width when the item count exceeds MaxDropDownItems, and sets DropDownWidth to the widest measured value.

Public Shared Function AdjustComboBoxWidth(ByVal sender As Object, ByVal e As EventArgs)
    Dim senderComboBox  = DirectCast(sender, ComboBox)
    Dim width           As Integer = senderComboBox.DropDownWidth
    Dim g               As Graphics = senderComboBox.CreateGraphics()
    Dim font            As Font = senderComboBox.Font

    Dim vertScrollBarWidth As Integer = If(
        (senderComboBox.Items.Count > senderComboBox.MaxDropDownItems),
        SystemInformation.VerticalScrollBarWidth,
        0)

    Dim newWidth As Integer
    For Each s As String In DirectCast(sender, ComboBox).Items
        newWidth = CInt(g.MeasureString(s, font).Width) + vertScrollBarWidth
        If width < newWidth Then
            width = newWidth
        End If
    Next

    senderComboBox.DropDownWidth = width
    Return False
End Function

Wire it up to the DropDown event of any ComboBox so it runs each time the list opens. That way it adapts if the items change between openings:

AddHandler comboBox1.DropDown, AddressOf AdjustComboBoxWidth

Because the function signature matches the standard EventHandler delegate (sender As Object, e As EventArgs), the same shared function can be reused across every ComboBox on every form in the project without duplication.

Tip: Graphics.MeasureString can slightly overestimate string width due to GDI character spacing. If you find the dropdown a touch too wide, subtract a small constant (typically 2 to 4 pixels) from newWidth after measuring. Alternatively, use TextRenderer.MeasureText with TextFormatFlags.NoPadding for a tighter and more accurate measurement that matches how Windows Forms actually renders text.

When to use this
  • Any ComboBox whose items are populated at runtime from a database or a dynamic source where the longest value is not known at design time.
  • Forms where the ComboBox width is constrained by the layout and cannot simply be made wider to accommodate all content.
  • Shared utility libraries where a single reusable handler can be attached to all ComboBox controls across a large Windows Forms application.
Found this useful? Drop a comment below if you have a variation or ran into an edge case I did not cover.

VB.NET : How to assign shortcut keys to the ToolStripButton?

ToolStripButton does not have a ShortcutKeys property the way a ToolStripMenuItem does. If you want a function key or any other keyboard shortcut to trigger a toolbar button, you need to intercept the keystroke at the form level yourself.

The most common scenario is a toolbar with an Execute or Refresh button that users expect to trigger with F5, matching the behaviour they know from Visual Studio, SQL Server Management Studio, and similar tools.

The fix

Override ProcessCmdKey on the form and call PerformClick on the target ToolStripButton when the matching key is pressed. ProcessCmdKey intercepts keystrokes before any focused control gets a chance to handle them, which makes it the right place for form-wide shortcuts.

' Assigning Shortcut Keys to ToolStrip Buttons
Protected Overrides Function ProcessCmdKey(
    ByRef msg      As System.Windows.Forms.Message,
    ByVal keyData  As System.Windows.Forms.Keys) As Boolean

    Select Case keyData
        Case Keys.F5
            ExecuteToolStripButton.PerformClick()
        Case Else
            'Do Nothing
    End Select

    Return MyBase.ProcessCmdKey(msg, keyData)
End Function

Returning MyBase.ProcessCmdKey(msg, keyData) at the end is important. It passes any unhandled keys back up the chain so that standard shortcuts such as Ctrl+C, Ctrl+Z, and arrow key navigation continue to work normally throughout the form.

Tip: To assign modifier combinations such as Ctrl+F5 or Shift+F5, combine the key values with the bitwise Or operator: Case Keys.F5 Or Keys.Control. The keyData parameter includes modifier flags, so this comparison works exactly as expected.

Handling multiple shortcuts

The Select Case block scales cleanly to as many shortcuts as you need. Add one Case per key combination and call PerformClick on the corresponding button:

Protected Overrides Function ProcessCmdKey(
    ByRef msg      As System.Windows.Forms.Message,
    ByVal keyData  As System.Windows.Forms.Keys) As Boolean

    Select Case keyData
        Case Keys.F5
            ExecuteToolStripButton.PerformClick()
        Case Keys.F5 Or Keys.Control
            CancelToolStripButton.PerformClick()
        Case Keys.F2
            EditToolStripButton.PerformClick()
        Case Else
            'Do Nothing
    End Select

    Return MyBase.ProcessCmdKey(msg, keyData)
End Function

When to use this
  • Any form with a ToolStrip where users expect keyboard shortcuts to match familiar tools such as SSMS, Visual Studio, or Excel.
  • Data entry forms where a single Execute or Save button needs to be reachable from the keyboard without the user moving their hands to the mouse.
  • Situations where adding a ToolStripMenuItem with a ShortcutKeys property is not appropriate because the menu item itself should not be visible to users.
Found this useful? Drop a comment below if you have a variation or ran into an edge case I did not cover.

VB.NET : How to draw outline around a borderless form?


'Paints a thin border around the form
    Protected Overrides Sub OnPaintBackground(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaintBackground(e)

        Dim rect As New Rectangle(0, 0, Me.ClientSize.Width - 1, Me.ClientSize.Height - 1)
        e.Graphics.DrawRectangle(Pens.SkyBlue, rect)
    End Sub


P.S. Inherited from how-to-draw-outline-around-a-borderless-form