Making a combobox autofill

TheWizardofInt

Junior Contributor
Joined
Dec 31, 1969
Messages
333
Location
Orlando, FL
I am trying to make a VB.Net form autofill from the contents of its drop down, so in this case if you type H and Hartford is in the drop down, then it autofills 'Hartford'

Code:
  ' Constant
Public Const CB_SELECTSTRING = &H14D
  ' API Declarations
    Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
        (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, _
            ByVal lParam As String) As Integer

Private Sub cmbCity_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles cmbCity.KeyPress
        Dim APIRetVal As Integer
        Dim sText As String

        Dim KeyAscii As String = e.KeyChar
        With cmbCity
            If Not (KeyAscii = Chr(8) Or KeyAscii = Chr(27) Or KeyAscii = Chr(13)) Then
                If .SelectionLength > 0 Then
                    sText = Mid(.Text, 1, .SelectionStart) & KeyAscii
                Else
                    sText = .Text & KeyAscii
                End If

                APIRetVal = SendMessage(.Handle, CB_SELECTSTRING, -1, sText)

                If APIRetVal <> -1 Then
                    .SelectionStart = Len(sText)
                    .SelectionLength = Len(.Text) - .SelectionStart + 1
                Else
                    .Text = sText
                    .SelectionStart = Len(sText) + 1
                End If

                KeyAscii = ""
            End If
        End With
    End Sub

It finds the selection as you F-11 through the program, then when the sub closes it retypes the Hh and selects it

Any idea where I am messing up here?
 
also noticed there is a lot of VB6 code in there - was this converted by the upgrade wizard? If you want to drop the compatability stuff the following is a more .Net way of doing things. (Although replacing the chr function can make it a bit long but more readable)

Visual Basic:
	Public Const CB_SELECTSTRING = &H14D
	' API Declarations
	Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
		(ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, _
			ByVal lParam As String) As Integer

	Private Sub cmbCity_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles cmbCity.KeyPress
		Dim APIRetVal As Integer
		Dim sText As String


		With cmbCity

If Not (e.KeyChar = Convert.ToChar(Keys.Back) Or e.KeyChar = Convert.ToChar(Keys.Escape) Or e.KeyChar = Convert.ToChar(Keys.Enter)) Then
				If .SelectionLength > 0 Then
					sText = .Text.Substring(0, .SelectionStart) & e.KeyChar

				Else
					sText = .Text & e.KeyChar
				End If

				APIRetVal = SendMessage(.Handle, CB_SELECTSTRING, -1, sText)

				If APIRetVal <> -1 Then
					.SelectionStart = sText.Length
					.SelectionLength = .Text.Length - .SelectionStart + 1
				Else
					.Text = sText
					.SelectionStart = sText.Length + 1
				End If

				e.Handled = True
			End If
		End With
	End Sub
 
Feeling bored so you might want to try this.
I've created a basic Combobox control with the functionality built in, not a complete control by any standards but a good starting point.
Create a new WindowsControl Project and paste this into a new class module and have a play.

Visual Basic:
Public Class AutoCompleteComboBox
    Inherits System.Windows.Forms.ComboBox


    Protected Overrides Sub OnKeyPress(ByVal e As System.Windows.Forms.KeyPressEventArgs)

        Dim sText As String = Text
        Dim i As Integer

        If e.KeyChar = Convert.ToChar(Keys.Back) Then
            Text = Text.Substring(0, SelectionStart - 1)
            sText = Text
        End If

        i = FindString(sText)

        If i >= 0 Then
            SelectedIndex = i
            [Select](sText.Length, Text.Length)
        End If
        MyBase.OnKeyPress(e)
    End Sub
End Class
 
Found a small bug and also added a property to allow the autocomplete to be turned on or off.

Visual Basic:
Public Class AutoCompleteComboBox
    Inherits System.Windows.Forms.ComboBox


    Protected _AutoCompleteEnabled As Boolean = True

    <System.ComponentModel.Category("Behavior"), System.ComponentModel.Description("Enables or disables the autocompletion functionality")> _
    Public Property AutoCompleteEnabled() As Boolean
        Get
            Return _AutoCompleteEnabled
        End Get
        Set(ByVal Value As Boolean)
            _AutoCompleteEnabled = Value
        End Set
    End Property

    Protected Overrides Sub OnKeyPress(ByVal e As System.Windows.Forms.KeyPressEventArgs)

        If _AutoCompleteEnabled = True Then  'Only do something if autocomplete is enabled
            Dim sText As String = Text
            Dim i As Integer

            If e.KeyChar = Convert.ToChar(Keys.Back) Then
                If Text.Length = 0 Then Return 'Don't backspace when nothing there
                Text = Text.Substring(0, SelectionStart - 1)
                sText = Text
            End If

            i = FindString(sText)

            If i >= 0 Then
                SelectedIndex = i
                [Select](sText.Length, Text.Length)
            End If
        End If
        MyBase.OnKeyPress(e)
    End Sub
End Class
 
Hello, I'm new here.. and found this very usefull. The only problem I found was when there was text in the box, you put the cursor at the beginning of the text, and hit backspace. We'd get a nice error. I fixed it with

Visual Basic:
If SelectionStart = 0 And SelectionLength = 0 Then Return

So the whole thing looks like:

Visual Basic:
Public Class AutoCompleteComboBox
    Inherits System.Windows.Forms.ComboBox


    Protected _AutoCompleteEnabled As Boolean = True

    <System.ComponentModel.Category("Behavior"), System.ComponentModel.Description("Enables or disables the autocompletion functionality")> _
    Public Property AutoCompleteEnabled() As Boolean
        Get
            Return _AutoCompleteEnabled
        End Get
        Set(ByVal Value As Boolean)
            _AutoCompleteEnabled = Value
        End Set
    End Property

    Protected Overrides Sub OnKeyPress(ByVal e As System.Windows.Forms.KeyPressEventArgs)

        If _AutoCompleteEnabled = True Then  'Only do something if autocomplete is enabled
            Dim sText As String = Text
            Dim i As Integer

            If e.KeyChar = Convert.ToChar(Keys.Back) Then
                If Text.Length = 0 Then Return 'Don't backspace when nothing there
                If SelectionStart = 0 And SelectionLength = 0 Then Return 'There's nothing to delete
                Text = Text.Substring(0, SelectionStart - 1)
                sText = Text
            End If

            i = FindString(sText)

            If i >= 0 Then
                SelectedIndex = i
                [Select](sText.Length, Text.Length)
            End If
        End If
        MyBase.OnKeyPress(e)
    End Sub
End Class
 
Back
Top