Link to home
Start Free TrialLog in
Avatar of bradwebber
bradwebber

asked on

Custom ComboBox Problem

I am trying to create a custom ComboBox control. I have inherited from the standard ComboBox control. When the user types something into my custom ComboBox I want the ComboBox to drop down the item list. To do this I have simply placed the following line in the KeyUp event of my custom ComboBox:

me.DroppedDown = True

The item list drops down as expected, but the problem is that the cursor then disappears. I have to press the Escape key or click the mouse button to make the cursor reappear, but the item list then retracts.

How can I drop down the item list without having the mouse cursor disappear?

(I am using VB.NET and VS2003)
Avatar of S-Twilley
S-Twilley

what are u trying to achieve exactly? an auto-suggest
Avatar of bradwebber

ASKER

Yeah, pretty much. What I am wanting to do is create a dynamic ComboBox that displays a list of matching items in it's item list (rather than displaying all items and simply selecting the first match).

If the ComboBox contains a match to the user input, the ComboBox will drop down its item list and the user can select the appropriate item.
Well... im not sure it's possible to type into a combo box and have the dropdown visible as well... i could be wrong... you could do it so you type in there, then when you click the drop down, it shows items which are like the text entered.

if you know some where which has a similar control (used in some windows program, point it out so i know what it is like)

assuming that its not possible to have the drop down visible and have the user type... you could use a textbox, a dropdown button, and a listbox... prolly won't look as pretty but might be an easy workaround
I can type into the ComboBox when the the dropdown is visible, it is just that the cursor is invisible when I do this. It turns out to be a big problem because the user can't select any of the items in the dropdown (because they can't see the cursor).

I was thinking of building my own from scratch (i.e. not inheriting from ComboBox) but I don't know how to paint the dropdown portion of the control. How can the standard ComboBox control paint its dropdown area when the actual height of the control is considerably smaller?
im guessing the dropdown part is a seperate window created by the control itself...

and sorry, i slightly misunderstood your meaning of cursor... lots of people on here confuse the cursor with the caret and I just assumed you meant caret...  I just tried what you're doing any have noticed that the cursor is invisible when within the bounds of the form (when the droplist is down and your typing).  I'll see if i can tweak it somehow to keep it visible
That would be great. If it could be kept visible then what I need to to is fairly simple.

Cheers.
weird... not sure what difference you have but when i push Esc... the list retracts, then reappears (because of the Esc keyup event), but the mouse is then visible... which suggests that it's possible for a cursor to be above the dropdown and still be typing
Sorry, you are right. I had some additional code in the keyup event. Yep, when I press the escape key now the dropdown reappears and the cursor remains on screen.

I have tried using SendKeys.Send("ESC}") in the keyup event to simulate pressing the escape key, but I couldn't get it to work properly.
I've tried using the keybd_event and had no luck with that either....

when you put a combobox at the bottom of the form and pull down the list, it goes past the bounds of the form which gives you the impression the dropdown part is it's own window... I suppose if you were to design your own, you could have a borderless form, with a listbox and use that as the dropdown list... and then the combobox is just textbox with a button for pulling down the list... and when that's click, the borderless form is lined up to the combo box and then shown... clicking on an item i nthe list sets the textbox and hides the form... but also taking the focus away from the form closes it
Here's a customized auto-complete combobox class, I've used it a lot and it works very well:

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.KeyPressEventArgs) Handles MyBase.KeyPress
        Dim intIndex As Integer
        Dim strEntry As String

        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.KeyChar)) And (Not Char.IsWhiteSpace(e.KeyChar)) Then  '< 32 Or KeyAscii > 127 Then
            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
Hi amyhxu,

What I really need my combo box to do is to automatically display the dropdown when the user starts typing (and there is a matching entry in the list). The autocomplete functionality that you have provided is great, but I won't be able to use it effectively unless I can also automatically display the dropdown.
I did some test using autocomplete combobox with the auto dropdown display, and it worked.

    Private WithEvents cb As AutoCompleteCombo

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        'Fill myTable first

        cb = New AutoCompleteCombo
        Me.Controls.Add(cb)
        cb.Location = New Point(100, 100)
        cb.DataSource = myTable
        cb.DisplayMember = "Col1"
        cb.ValueMember = "Col2"
        cb.SelectedIndex = -1

    End Sub

    Private Sub cb_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles cb.KeyDown

        cb.DroppedDown = True

    End Sub
Hi there amyhxu, thanks for your reply.

What I would like to be able to do is to encapsulate the cb.DroppedDown = True into the custom control, rather than having to put it on the form that contains the control. I have not been able to get it to work though when I attempt to do this.

Sorry for being so picky! :)
ASKER CERTIFIED SOLUTION
Avatar of amyhxu
amyhxu

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi there Amyhxu,

Thank you very much for your solution!