[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 922
  • Last Modified:

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)
0
bradwebber
Asked:
bradwebber
  • 7
  • 5
  • 3
1 Solution
 
S-TwilleyCommented:
what are u trying to achieve exactly? an auto-suggest
0
 
bradwebberAuthor Commented:
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.
0
 
S-TwilleyCommented:
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
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
bradwebberAuthor Commented:
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?
0
 
S-TwilleyCommented:
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
0
 
bradwebberAuthor Commented:
That would be great. If it could be kept visible then what I need to to is fairly simple.

Cheers.
0
 
S-TwilleyCommented:
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
0
 
bradwebberAuthor Commented:
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.
0
 
S-TwilleyCommented:
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
0
 
amyhxuCommented:
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
0
 
bradwebberAuthor Commented:
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.
0
 
amyhxuCommented:
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
0
 
bradwebberAuthor Commented:
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! :)
0
 
amyhxuCommented:
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.KeyPressEventArgs) Handles MyBase.KeyPress
        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.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
0
 
bradwebberAuthor Commented:
Hi there Amyhxu,

Thank you very much for your solution!
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

  • 7
  • 5
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now