brian_leighty
asked on
HELP!!....I have created a user interface to a SQL database using VB.NET....I have a combobox that I would like to autocomplete using the valuse from a specific field...
When the form loads the combobox throughout the form load with values from there specific fields...(ex. states go in cbcuststate2)
I have one combo that fills with all the customer names in the databases...I want my users to be able to type in the first letter and the combobox either autocomplete per letter typed...or a dropdown happend with all the customer names that match the letters typed.....
Thank You Very Much...
Brian
I have one combo that fills with all the customer names in the databases...I want my users to be able to type in the first letter and the combobox either autocomplete per letter typed...or a dropdown happend with all the customer names that match the letters typed.....
Thank You Very Much...
Brian
ASKER
How do I use this code.....I cannot get it to work...
Here you go. It worked on my computer, hopefully it will work on yours. If your items contains characters other than numbers, letters and space, you'll need to modify this a little bit. If you are having problem with this, let me know.
Option Strict On
Option Explicit On
Imports System.Windows.Forms
Public Class AutoCompleteCombo
Inherits ComboBox
Private mResetOnClear As Boolean = False
Protected Overrides Sub RefreshItem(ByVal index As Integer)
MyBase.RefreshItem(index)
End Sub
Protected Overrides Sub SetItemsCore(ByVal items As System.Collections.IList)
MyBase.SetItemsCore(items)
End Sub
Public Shadows Sub KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPr
Dim intIndex As Integer
Dim strEntry As String
Me.DroppedDown = True
If Char.IsControl(e.KeyChar) Then
If MyBase.SelectionStart <= 1 Then
If mResetOnClear Then
MyBase.SelectedIndex = 0
MyBase.SelectAll()
Else
MyBase.Text = String.Empty
MyBase.SelectedIndex = -1
MyBase.SelectedIndex = -1
End If
e.Handled = True
Exit Sub
End If
If MyBase.SelectionLength = 0 Then
strEntry = MyBase.Text.Substring(0, MyBase.Text.Length - 1)
Else
strEntry = MyBase.Text.Substring(0, MyBase.SelectionStart - 1)
End If
ElseIf (Not Char.IsLetterOrDigit(e.Key
Exit Sub
Else
If MyBase.SelectionLength = 0 Then
strEntry = UCase(MyBase.Text & e.KeyChar)
Else
strEntry = MyBase.Text.Substring(0, MyBase.SelectionStart) & e.KeyChar
End If
End If
intIndex = MyBase.FindString(strEntry
If intIndex <> -1 Then
MyBase.SelectedIndex = intIndex
MyBase.SelectionStart = strEntry.Length
MyBase.SelectionLength = MyBase.Text.Length - MyBase.SelectionStart
End If
e.Handled = True
Exit Sub
End Sub
Public Property ResetOnClear() As Boolean
Get
Return mResetOnClear
End Get
Set(ByVal Value As Boolean)
mResetOnClear = Value
End Set
End Property
End Class
AutoCompletion class:
Imports System.Runtime.InteropServ ices
Public Class AutoComplete : Implements IDisposable
' HKEY_CLASSES_ROOT\Interfac e\{0000010 1-0000-000 0-C000-000 000000046} \IEnumStri ng
<ComImport(), InterfaceType(ComInterface Type.Inter faceIsIUnk nown), Guid("00000101-0000-0000-C 000-000000 000046")> _
Private Interface IEnumString
Function [Next](ByVal celt As Integer, ByVal rgelt() As String, ByRef pceltFetched As Integer) As Integer
Function Skip(ByVal celt As Integer) As Integer
Function Reset() As Integer
Sub Clone(ByRef ppenum As IEnumString)
End Interface 'IEnumString'
<ComImport(), InterfaceType(ComInterface Type.Inter faceIsIUnk nown), Guid("EAC04BC0-3791-11D2-B B95-006097 7B464C")> _
Private Interface IAutoComplete
Function Init(ByVal hwndEdit As IntPtr, _
<MarshalAs(UnmanagedType.I Unknown)> ByVal punkACL As Object, _
ByVal pwszRegKeyPath As String, _
ByVal pwszQuickComplete As String) As Int32
' We must use <PreserveSig()> otherwise after using
' autocomplete, fields will not return the next time.
<PreserveSig()> _
Function Enable(<[In]()> ByVal fEnable As Boolean) As Boolean
<PreserveSig()> _
Function SetOptions(<[In]()> ByVal dwFlag As UInt32) As Integer
<PreserveSig()> _
Function GetOptions(<Out()> ByRef pdwFlag As UInt32) As Integer
End Interface 'IAutoComplete.
Private Enum ShowOptions
None = 0
AutoSuggest = &H1
AutoAppend = &H2
Search = &H4
FilterPrefixes = &H8
UseTab = &H10
UpDownKeyDropsList = &H20
RightToLeft = &H40
End Enum 'ShowOptions'
Private _enabled As Boolean
Private _autoComp As Type
Private IAutoComp As IAutoComplete
Private Class EnumString : Implements UCOMIEnumString
' UCOMIEnumString is the same as the IEnumString interface
' see more at Msdn on http://msdn.microsoft.com/library/d...mi_d2l_89uv.asp
Private _strArray As ArrayList
Private _pos As Integer = 0
Public Property Array() As ArrayList
Get
Return _strArray
End Get
Set(ByVal Value As ArrayList)
_strArray = Value
End Set
End Property 'Array'
Public Function [Next](ByVal celt As Integer, ByVal rgelt As String(), _
ByRef pceltFetched As Integer) As Integer Implements UCOMIEnumString.Next
Dim retval As Integer = 1
pceltFetched = 0
While Not _pos = _strArray.Count AndAlso Not pceltFetched = celt
rgelt(pceltFetched) = _strArray(_pos)
pceltFetched += 1
_pos += 1
End While
If Not pceltFetched.CompareTo(cel t) = -1 Then
retval = 0
End If
Return retval
End Function
Public Function Skip(ByVal celt As Integer) As Integer Implements UCOMIEnumString.Skip
Dim retval As Integer = 1
_pos += celt
If Not _pos = _strArray.Count Then
retval = 0
End If
Return retval
End Function 'Skip'
Public Function Reset() As Integer Implements UCOMIEnumString.Reset
_pos = 0
Return _pos
End Function 'Reset'
Public Sub Clone(ByRef ppenum As UCOMIEnumString) Implements UCOMIEnumString.Clone
' create a Clone of this Class
ppenum = DirectCast(Me, EnumString)
End Sub 'Clone'
End Class 'EnumString'
Public Sub New(ByVal handleEdit As IntPtr, ByVal listWords As ArrayList, Optional ByVal registryPath As String = "", Optional ByVal quickComplete As String = "")
Dim iEnumList As New EnumString
iEnumList.Array = listWords
_autoComp = Type.GetTypeFromCLSID(New Guid("{00BB2763-6A77-11D0- A535-00C04 FD7D062}") )
IAutoComp = DirectCast(Activator.Creat eInstance( _autoComp) , _
IAutoComplete)
' Initialize IAutoComplete.
IAutoComp.Init(handleEdit, iEnumList, registryPath, quickComplete)
' Set IAutoComplete Options.
IAutoComp.SetOptions(Conve rt.ToUInt3 2(ShowOpti ons.AutoSu ggest Or _
ShowOptions.UpDownKeyDrops List Or ShowOptions.AutoAppend))
' Enable IAutoComplete.
IAutoComp.Enable(True)
End Sub 'New'
Public Sub Dispose() Implements System.IDisposable.Dispose
Marshal.ReleaseComObject(I AutoComp)
End Sub 'Dispose'
Public Property Enabled() As Boolean
Get
Return _enabled
End Get
Set(ByVal Value As Boolean)
_enabled = Value
If Value Then
IAutoComp.SetOptions(Conve rt.ToUInt3 2(ShowOpti ons.AutoSu ggest Or ShowOptions.UpDownKeyDrops List Or ShowOptions.AutoAppend))
Else
IAutoComp.SetOptions(Conve rt.ToUInt3 2(ShowOpti ons.None))
End If
End Set
End Property 'Enabled'
End Class 'AutoComplete'
Usage:
Dim listWords As New ArrayList
listWords.Add("Green")
listWords.Add("Red")
listWords.Add("Yellow")
listWords.Add("Blue")
listWords.Add("Magenta")
listWords.Add("Maroon")
listWords.Add("Cyan")
Dim completer As New AutoComplete(Me.TextBox1.H andle, listWords)
Bob
Imports System.Runtime.InteropServ
Public Class AutoComplete : Implements IDisposable
' HKEY_CLASSES_ROOT\Interfac
<ComImport(), InterfaceType(ComInterface
Private Interface IEnumString
Function [Next](ByVal celt As Integer, ByVal rgelt() As String, ByRef pceltFetched As Integer) As Integer
Function Skip(ByVal celt As Integer) As Integer
Function Reset() As Integer
Sub Clone(ByRef ppenum As IEnumString)
End Interface 'IEnumString'
<ComImport(), InterfaceType(ComInterface
Private Interface IAutoComplete
Function Init(ByVal hwndEdit As IntPtr, _
<MarshalAs(UnmanagedType.I
ByVal pwszRegKeyPath As String, _
ByVal pwszQuickComplete As String) As Int32
' We must use <PreserveSig()> otherwise after using
' autocomplete, fields will not return the next time.
<PreserveSig()> _
Function Enable(<[In]()> ByVal fEnable As Boolean) As Boolean
<PreserveSig()> _
Function SetOptions(<[In]()> ByVal dwFlag As UInt32) As Integer
<PreserveSig()> _
Function GetOptions(<Out()> ByRef pdwFlag As UInt32) As Integer
End Interface 'IAutoComplete.
Private Enum ShowOptions
None = 0
AutoSuggest = &H1
AutoAppend = &H2
Search = &H4
FilterPrefixes = &H8
UseTab = &H10
UpDownKeyDropsList = &H20
RightToLeft = &H40
End Enum 'ShowOptions'
Private _enabled As Boolean
Private _autoComp As Type
Private IAutoComp As IAutoComplete
Private Class EnumString : Implements UCOMIEnumString
' UCOMIEnumString is the same as the IEnumString interface
' see more at Msdn on http://msdn.microsoft.com/library/d...mi_d2l_89uv.asp
Private _strArray As ArrayList
Private _pos As Integer = 0
Public Property Array() As ArrayList
Get
Return _strArray
End Get
Set(ByVal Value As ArrayList)
_strArray = Value
End Set
End Property 'Array'
Public Function [Next](ByVal celt As Integer, ByVal rgelt As String(), _
ByRef pceltFetched As Integer) As Integer Implements UCOMIEnumString.Next
Dim retval As Integer = 1
pceltFetched = 0
While Not _pos = _strArray.Count AndAlso Not pceltFetched = celt
rgelt(pceltFetched) = _strArray(_pos)
pceltFetched += 1
_pos += 1
End While
If Not pceltFetched.CompareTo(cel
retval = 0
End If
Return retval
End Function
Public Function Skip(ByVal celt As Integer) As Integer Implements UCOMIEnumString.Skip
Dim retval As Integer = 1
_pos += celt
If Not _pos = _strArray.Count Then
retval = 0
End If
Return retval
End Function 'Skip'
Public Function Reset() As Integer Implements UCOMIEnumString.Reset
_pos = 0
Return _pos
End Function 'Reset'
Public Sub Clone(ByRef ppenum As UCOMIEnumString) Implements UCOMIEnumString.Clone
' create a Clone of this Class
ppenum = DirectCast(Me, EnumString)
End Sub 'Clone'
End Class 'EnumString'
Public Sub New(ByVal handleEdit As IntPtr, ByVal listWords As ArrayList, Optional ByVal registryPath As String = "", Optional ByVal quickComplete As String = "")
Dim iEnumList As New EnumString
iEnumList.Array = listWords
_autoComp = Type.GetTypeFromCLSID(New Guid("{00BB2763-6A77-11D0-
IAutoComp = DirectCast(Activator.Creat
IAutoComplete)
' Initialize IAutoComplete.
IAutoComp.Init(handleEdit,
' Set IAutoComplete Options.
IAutoComp.SetOptions(Conve
ShowOptions.UpDownKeyDrops
' Enable IAutoComplete.
IAutoComp.Enable(True)
End Sub 'New'
Public Sub Dispose() Implements System.IDisposable.Dispose
Marshal.ReleaseComObject(I
End Sub 'Dispose'
Public Property Enabled() As Boolean
Get
Return _enabled
End Get
Set(ByVal Value As Boolean)
_enabled = Value
If Value Then
IAutoComp.SetOptions(Conve
Else
IAutoComp.SetOptions(Conve
End If
End Set
End Property 'Enabled'
End Class 'AutoComplete'
Usage:
Dim listWords As New ArrayList
listWords.Add("Green")
listWords.Add("Red")
listWords.Add("Yellow")
listWords.Add("Blue")
listWords.Add("Magenta")
listWords.Add("Maroon")
listWords.Add("Cyan")
Dim completer As New AutoComplete(Me.TextBox1.H
Bob
ASKER
I have know Idea how to use this code it looks way to advanced for me.....
Please Explain farther....I tried inserting but did not work..
Is there anyway the combobox has to be set up for this to work...
thanks
Please Explain farther....I tried inserting but did not work..
Is there anyway the combobox has to be set up for this to work...
thanks
Instead of dragging one generic combobox from the toolbox, you should declare the autocomplete combo in code:
e.g.
First add this class to your project, then in your form
Dim cb As AutoCompleteCombo
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
cb = New AutoCompleteCombo
Me.Controls.Add(cb)
cb.Location = New System.Drawing.Point(100, 100)
cb.Size = New System.Drawing.Size(300, 24)
cb.TabIndex = 1
...
End Sub
e.g.
First add this class to your project, then in your form
Dim cb As AutoCompleteCombo
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
cb = New AutoCompleteCombo
Me.Controls.Add(cb)
cb.Location = New System.Drawing.Point(100, 100)
cb.Size = New System.Drawing.Size(300, 24)
cb.TabIndex = 1
...
End Sub
Brian,
Who are you talking to about being too advanced? If it was me, and you need this for a combo box, then you need this:
Private Declare Function FindWindowEx _
Lib "user32" Alias "FindWindowExA" _
(ByVal hWnd1 As IntPtr, ByVal hWnd2 As IntPtr, _
ByVal lpsz1 As String, ByVal lpsz2 As String) As IntPtr
Public Function ComboBoxEditHandle(ByVal comboCurrent As ComboBox) As IntPtr
' Get the handle of the inner Edit control.
Dim editHandle As IntPtr = FindWindowEx(comboCurrent. Handle, IntPtr.Zero, vbNullString, vbNullString)
Return editHandle
End Function 'ComboBoxEditHandle'
Usage:
Dim listWords As New ArrayList
listWords.Add("Green")
listWords.Add("Red")
listWords.Add("Yellow")
listWords.Add("Blue")
listWords.Add("Magenta")
listWords.Add("Maroon")
listWords.Add("Cyan")
Dim completer As New AutoComplete(ComboBoxEditH andle(Me.C omboBox1), listWords)
Bob
Who are you talking to about being too advanced? If it was me, and you need this for a combo box, then you need this:
Private Declare Function FindWindowEx _
Lib "user32" Alias "FindWindowExA" _
(ByVal hWnd1 As IntPtr, ByVal hWnd2 As IntPtr, _
ByVal lpsz1 As String, ByVal lpsz2 As String) As IntPtr
Public Function ComboBoxEditHandle(ByVal comboCurrent As ComboBox) As IntPtr
' Get the handle of the inner Edit control.
Dim editHandle As IntPtr = FindWindowEx(comboCurrent.
Return editHandle
End Function 'ComboBoxEditHandle'
Usage:
Dim listWords As New ArrayList
listWords.Add("Green")
listWords.Add("Red")
listWords.Add("Yellow")
listWords.Add("Blue")
listWords.Add("Magenta")
listWords.Add("Maroon")
listWords.Add("Cyan")
Dim completer As New AutoComplete(ComboBoxEditH
Bob
Adding items to or setting datasource for the AutoCompleteCombo uses the same code you used for populating a normal ComboBox.
BTW, the AutoComplete class binds an edit control to the Internet Explorer-style auto-completion.
Bob
Bob
ASKER
LearnedOne I really cannot get your code to work...
I made a class and changed the combobox to use that class and I get an error with listwords in your class...
it says that listwords is not defined
I made a class and changed the combobox to use that class and I get an error with listwords in your class...
it says that listwords is not defined
Did you get this code, too?
Dim listWords As New ArrayList
listWords.Add("Green")
listWords.Add("Red")
listWords.Add("Yellow")
listWords.Add("Blue")
listWords.Add("Magenta")
listWords.Add("Maroon")
listWords.Add("Cyan")
Bob
Dim listWords As New ArrayList
listWords.Add("Green")
listWords.Add("Red")
listWords.Add("Yellow")
listWords.Add("Blue")
listWords.Add("Magenta")
listWords.Add("Maroon")
listWords.Add("Cyan")
Bob
ASKER
Amyhxu your code works perfect but when I hit the enter key it backspaces and if nothing exist then I get an error...currently debugging to find out where....
ASKER
well the items that I'm adding come from a SQL field....ignore my ignorance but does the "listwords.add" add items to the combobox manually or from a field....
just for shits and giggles where would I put the listwords code at....usage code
just for shits and giggles where would I put the listwords code at....usage code
Dim listWords As New ArrayList
Dim completer As New AutoComplete(ComboBoxEditH andle(Me.C omboBox1), listWords)
This is the list of words that are to be used for the AutoComplete.
Bob
Dim completer As New AutoComplete(ComboBoxEditH
This is the list of words that are to be used for the AutoComplete.
Bob
ASKER
so if it type in "M" i get a "magenta" in the box and if I type in "MAR" then it changes to "maroon"
thanks
thanks
The list of words that you add to listWords control what is shown in the auto-completion.
Bob
Bob
ASKER
but I need to autocomplete what is in a SQL field.... "customer names"
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Also, make sure you are using .NET framework 1.1 and service Pack1.
Here's the autocomplete combo with auto expand feature I modified from the example above, and it's probably a better choice for your requirement:
https://www.experts-exchange.com/questions/21379445/Custom-ComboBox-Problem.html