2010-09-12 63 views
14

在我的一個WinForms應用程序中,我有一個帶有ComboBox的窗口供用戶從中選擇客戶。SubString上的ComboBox自動完成

在該列表框中的客戶都是這種格式:「客戶ID - 客戶名稱」,例如「004540 - 羅斯文商貿」

本機的WinForms組合框有內置的自動完成功能,而且運作良好:在問題在於它只能通過從組合框列表的每個項目的字符串的開頭匹配而不是從任何位置(子字符串)進行匹配。

我希望我的用戶能夠做的是無論是哪種類型的客戶ID或客戶名稱,因爲高級用戶熟悉大多數客戶ID,而新員工可以從中輸入客戶名稱並獲得自動完成無論如何。 這意味着我實際上希望從輸入文本是組合框項目的子字符串的列表中尋找最佳匹配項。

對於這種場景,通常會建議一種解決方案,即創建一個隱藏列表框,該列表框僅在用戶輸入時才顯示,但我對此感到不滿意,因爲它感覺像是一個快速入侵併且不易重複使用,並且與標準ComboBox控件相比可能看起來和行爲不一致。

我試圖使用DroppedDown屬性來使列表出現,並使用SelectedIndex來設置項目,但當我這樣做時,組合框的文本框的內容被重置,而我只想要「最好的匹配項「從ComboBox列表中突出顯示(我需要」建議「而不是」追加「,追加模式無法真正與子字符串匹配使用)。

我認爲一定有更好的辦法? 如果有人知道這樣做的自定義/第三方控件,我也不反對購買一個。

謝謝。我正在用C#編寫WinForms,使用.Net Framework 3.5編程。

回答

7

嗯,我有一些代碼供您嘗試。它不是一個組合框,但是它是一個自動完成的文本框,其修改按照您的請求執行。

將代碼複製到新窗體中。然後在做任何事之前,保存並構建。然後轉到表單設計器並將新的ClsCustomAutoCompleteTextbox拖到您的表單上。

然後你應該可以運行它。我意識到你想要C#(至少現在我意識到了)。試試這在VB中,看看這是你想要的,我可以將其轉換爲C#。

Public Class Form1 
    Dim MasterList As New List(Of String) 


    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
    Dim L As New List(Of String) 

    L.Add("123123 - Bob") 
    L.Add("534543 - Sally") 
    L.Add("123123 - George") 
    L.Add("34213 - Happy") 

    MasterList = L 

    Me.ClsCustomAutoCompleteTextbox1.AutoCompleteList = L 
    End Sub 

    Private Sub ClsCustomAutoCompleteTextbox1_BeforeDisplayingAutoComplete(ByVal sender As Object, ByVal e As clsCustomAutoCompleteTextbox.clsAutoCompleteEventArgs) Handles ClsCustomAutoCompleteTextbox1.BeforeDisplayingAutoComplete 

    Dim Name As String = Me.ClsCustomAutoCompleteTextbox1.Text.ToLower 

    Dim Display As New List(Of String) 

    For Each Str As String In MasterList 
     If Str.ToLower.IndexOf(Name) > -1 Then 
     Display.Add(Str) 
     End If 
    Next 

    e.AutoCompleteList = Display 
    e.SelectedIndex = 0 
    End Sub 
End Class 


#Region "clsCustomAutoCompleteTextbox" 
Public Class clsCustomAutoCompleteTextbox 
    Inherits TextBox 
    Event BeforeDisplayingAutoComplete(ByVal sender As Object, ByVal e As clsAutoCompleteEventArgs) 
    Event ItemSelected(ByVal sender As Object, ByVal e As clsItemSelectedEventArgs) 


    Public test As New List(Of String) 
    Public Tabs As Integer = 0 


    Private Function GetLastFunction(Optional ByVal Deep As Integer = 1) As System.Reflection.MethodInfo 
    Dim ST As New StackTrace 
    Dim Frame As StackFrame = ST.GetFrame(Deep) 

    Return Frame.GetMethod() 
    End Function 

    Private Sub TempLogStart() 
    'Dim Meth As System.Reflection.MethodInfo = GetLastFunction(3) 

    'test.Add(Now & " - " & New String(" ", Tabs * 2) & "Started " & Meth.Module.Name & "." & Meth.Name) 

    'Tabs += 1 
    End Sub 

    Private Sub TempLogStop() 
    ' Dim Meth As System.Reflection.MethodInfo = GetLastFunction(3) 

    ' Tabs -= 1 

    ' test.Add(Now & " - " & New String(" ", Tabs * 2) & "Stopped " & Meth.Module.Name & "." & Meth.Name) 
    End Sub 

    Public Enum SelectOptions 
    OnEnterPress = 1 
    OnSingleClick = 2 
    OnDoubleClick = 4 
    OnTabPress = 8 
    OnRightArrow = 16 
    OnEnterSingleClick = 3 
    OnEnterSingleDoubleClicks = 7 
    OnEnterDoubleClick = 5 
    OnEnterTab = 9 
    'OnItemChange = 32 
    End Enum 

    Private mSelStart As Integer 
    Private mSelLength As Integer 

    Private myAutoCompleteList As New List(Of String) 
    Private WithEvents myLbox As New ListBox 
    Private WithEvents myForm As New Form 
    Private WithEvents myParentForm As Form 

    Private DontHide As Boolean = False 
    Private SuspendFocus As Boolean = False 

    Dim Args As clsAutoCompleteEventArgs 

    WithEvents HideTimer As New Timer() 
    WithEvents FocusTimer As New Timer() 

    Private myShowAutoCompleteOnFocus As Boolean 
    Private myAutoCompleteFormBorder As System.Windows.Forms.FormBorderStyle = FormBorderStyle.None 
    Private myOnEnterSelect As Boolean 
    Private mySelectionMethods As SelectOptions = (SelectOptions.OnDoubleClick Or SelectOptions.OnEnterPress) 
    Private mySelectTextAfterItemSelect As Boolean = True 


    Public Property SelectTextAfterItemSelect() As Boolean 
    Get 
     Return mySelectTextAfterItemSelect 
    End Get 
    Set(ByVal value As Boolean) 
     mySelectTextAfterItemSelect = value 
    End Set 
    End Property 

    <System.ComponentModel.Browsable(False)> _ 
    Public Property SelectionMethods() As SelectOptions 
    Get 
     Return mySelectionMethods 
    End Get 
    Set(ByVal value As SelectOptions) 
     mySelectionMethods = value 
    End Set 
    End Property 

    Public Property OnEnterSelect() As Boolean 
    Get 
     Return myOnEnterSelect 
    End Get 
    Set(ByVal value As Boolean) 
     myOnEnterSelect = value 
    End Set 
    End Property 

    Public Property AutoCompleteFormBorder() As System.Windows.Forms.FormBorderStyle 
    Get 
     Return myAutoCompleteFormBorder 
    End Get 
    Set(ByVal value As System.Windows.Forms.FormBorderStyle) 
     myAutoCompleteFormBorder = value 
    End Set 
    End Property 

    Public Property ShowAutoCompleteOnFocus() As Boolean 
    Get 
     Return myShowAutoCompleteOnFocus 
    End Get 
    Set(ByVal value As Boolean) 
     myShowAutoCompleteOnFocus = value 
    End Set 
    End Property 

    Public ReadOnly Property Lbox() As ListBox 
    Get 
     Return myLbox 
    End Get 
    End Property 

    Public Property AutoCompleteList() As List(Of String) 
    Get 
     Return myAutoCompleteList 
    End Get 
    Set(ByVal value As List(Of String)) 
     myAutoCompleteList = value 
    End Set 
    End Property 

    Private Sub TryHideFormWindowsDeactivated() 

    End Sub 

    Private Declare Auto Function GetForegroundWindow Lib "user32.dll"() As IntPtr 
    Private Declare Auto Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hWnd As IntPtr, ByRef ProcessID As Integer) As Integer 

    Private Function IsCurProcess(ByVal P As Process) As Boolean 
    Dim Ptr As IntPtr = P.MainWindowHandle 


    End Function 

    Private Function AppHasFocus(Optional ByVal ExeNameWithoutExtension As String = "") As Boolean 
    Dim Out As Boolean = False 
    Dim PID As Integer = 0 

    TempLogStart() 

    If ExeNameWithoutExtension = "" Then 
     ExeNameWithoutExtension = Process.GetCurrentProcess.ProcessName 
    End If 
    Dim activeHandle As IntPtr = GetForegroundWindow() 
    Call GetWindowThreadProcessId(activeHandle, PID) 
    If PID > 0 Then 
     'For Each p As Process In Process.GetProcessesByName(ExeNameWithoutExtension) 
     If PID = Process.GetCurrentProcess.Id Then 
     Out = True 
     'Exit For 
     End If 
     ' Next 
    End If 

    TempLogStop() 

    Return Out 
    End Function 

    Private Sub SaveSelects() 
    Me.mSelStart = Me.SelectionStart 
    Me.mSelLength = Me.SelectionLength 
    End Sub 

    Private Sub LoadSelects() 
    Me.SelectionStart = Me.mSelStart 
    Me.SelectionLength = Me.mSelLength 
    End Sub 

    Private Sub ShowAutoComplete() 
    TempLogStart() 

    Args = New clsAutoCompleteEventArgs() 

    With Args 
     .Cancel = False 
     .AutoCompleteList = Me.myAutoCompleteList 

     If myLbox.SelectedIndex = -1 Then 
     .SelectedIndex = 0 
     Else 
     .SelectedIndex = myLbox.SelectedIndex 
     End If 
    End With 

    RaiseEvent BeforeDisplayingAutoComplete(Me, Args) 

    Me.myAutoCompleteList = Args.AutoCompleteList 

    'If Me.myAutoCompleteList IsNot Nothing AndAlso Me.myAutoCompleteList.Count - 1 < Args.SelectedIndex Then 
    ' Args.SelectedIndex = Me.myAutoCompleteList.Count - 1 
    'End If 

    If Not Args.Cancel AndAlso Args.AutoCompleteList IsNot Nothing AndAlso Args.AutoCompleteList.Count > 0 Then 
     Call DoShowAuto() 
    Else 
     Call DoHideAuto() 
    End If 
    TempLogStop() 
    End Sub 

    Private Sub DoShowAuto() 
    Call SaveSelects() 

    TempLogStart() 
    Static First As Boolean = True 
    myLbox.BeginUpdate() 
    Try 
     myLbox.Items.Clear() 
     myLbox.Items.AddRange(Me.myAutoCompleteList.ToArray) 

     Call Me.MoveLBox(Args.SelectedIndex) 
    Catch ex As Exception 
    End Try 
    myLbox.EndUpdate() 


    myParentForm = GetParentForm(Me) 
    If myParentForm IsNot Nothing Then 
     myLbox.Name = "mmmlbox" & Now.Millisecond 
     If myForm.Visible = False Then 
     myForm.Font = Me.Font 
     myLbox.Font = Me.Font 

     myLbox.Visible = True 
     myForm.Visible = False 

     myForm.ControlBox = False 

     myForm.Text = "" 

     If First Then 
      myForm.Width = Me.Width 
      myForm.Height = 200 
     End If 

     First = False 

     If Not myForm.Controls.Contains(myLbox) Then myForm.Controls.Add(myLbox) 
     myForm.FormBorderStyle = FormBorderStyle.None 
     myForm.ShowInTaskbar = False 

     With myLbox 
      .Dock = DockStyle.Fill 
      .SelectionMode = SelectionMode.One 
     End With 

     'Frm.Controls.Add(myLbox) 

     DontHide = True 

     SuspendFocus = True 


     myForm.TopMost = True 
     myForm.FormBorderStyle = Me.myAutoCompleteFormBorder 

     myForm.BringToFront() 
     Call MoveDrop() 
     myForm.Visible = True 
     myForm.Show() 
     Call MoveDrop() 

     HideTimer.Interval = 10 

     Me.Focus() 

     SuspendFocus = False 

     HideTimer.Enabled = True 

     DontHide = False 

     Call LoadSelects() 
     End If 
    End If 
    TempLogStop() 

    End Sub 

    Sub MoveDrop() 

    TempLogStart() 
    Dim Pnt As Point = New Point(Me.Left, Me.Top + Me.Height + 2) 
    Dim ScreenPnt As Point = Me.PointToScreen(New Point(-2, Me.Height)) 

    'Dim FrmPnt As Point = Frm.PointToClient(ScreenPnt) 
    If myForm IsNot Nothing Then 
     myForm.Location = ScreenPnt 

     'myForm.BringToFront() 


     'myForm.Focus() 
     'myLbox.Focus() 

     'Me.Focus() 
    End If 
    TempLogStop() 
    End Sub 

    Sub DoHide(ByVal sender As Object, ByVal e As EventArgs) 

    TempLogStart() 
    Call HideAuto() 
    TempLogStop() 
    End Sub 

    Private Sub DFocus(Optional ByVal Delay As Integer = 10) 

    TempLogStart() 
    FocusTimer.Interval = Delay 
    FocusTimer.Start() 
    TempLogStop() 
    End Sub 

    Private Sub DoHideAuto() 

    TempLogStart() 
    myForm.Hide() 

    HideTimer.Enabled = False 
    FocusTimer.Enabled = False 
    TempLogStop() 
    End Sub 

    Private Sub HideAuto() 

    TempLogStart() 
    If myForm.Visible AndAlso HasLostFocus() Then 
     Call DoHideAuto() 
    End If 
    TempLogStop() 
    End Sub 

    Private Function HasLostFocus() As Boolean 

    TempLogStart() 
    Dim Out As Boolean 

    If Me.myForm Is Nothing OrElse myForm.ActiveControl IsNot Me.myLbox Then 
     Out = True 
    End If 

    If Me.myParentForm Is Nothing OrElse Me.myParentForm.ActiveControl IsNot Me Then 
     Out = True 
    End If 

    TempLogStop() 
    Return Out 
    End Function 

    Private Function GetParentForm(ByVal InCon As Control) As Form 

    TempLogStart() 
    Dim TopCon As Control = FindTopParent(InCon) 
    Dim Out As Form = Nothing 

    If TypeOf TopCon Is Form Then 
     Out = CType(TopCon, Form) 
    End If 

    TempLogStop() 
    Return Out 
    End Function 

    Private Function FindTopParent(ByVal InCon As Control) As Control 

    TempLogStart() 
    Dim Out As Control 

    If InCon.Parent Is Nothing Then 
     Out = InCon 
    Else 
     Out = FindTopParent(InCon.Parent) 
    End If 

    TempLogStop() 
    Return Out 
    End Function 

    Public Class clsAutoCompleteEventArgs 
    Inherits EventArgs 

    Private myAutoCompleteList As List(Of String) 
    Private myCancel As Boolean 

    Private mySelectedIndex As Integer 

    Public Property SelectedIndex() As Integer 
     Get 
     Return mySelectedIndex 
     End Get 
     Set(ByVal value As Integer) 
     mySelectedIndex = value 
     End Set 
    End Property 

    Public Property Cancel() As Boolean 
     Get 
     Return myCancel 
     End Get 
     Set(ByVal value As Boolean) 
     myCancel = value 
     End Set 
    End Property 

    Public Property AutoCompleteList() As List(Of String) 
     Get 
     Return myAutoCompleteList 
     End Get 
     Set(ByVal value As List(Of String)) 
     myAutoCompleteList = value 
     End Set 
    End Property 
    End Class 

    Protected Overrides Sub OnKeyUp(ByVal e As System.Windows.Forms.KeyEventArgs) 

    TempLogStart() 
    TempLogStop() 
    MyBase.OnKeyUp(e) 

    Call ShowOnChar(Chr(e.KeyValue)) 
    End Sub 

    Private Sub ShowOnChar(ByVal C As String) 

    TempLogStart() 
    TempLogStop() 
    If IsPrintChar(C) Then 
     Call Me.ShowAutoComplete() 
    End If 
    End Sub 

    Private Function IsPrintChar(ByVal C As Integer) As Boolean 

    TempLogStart() 
    TempLogStop() 
    Return IsPrintChar(Chr(C)) 
    End Function 

    Private Function IsPrintChar(ByVal C As Byte) As Boolean 

    TempLogStart() 
    TempLogStop() 
    Return IsPrintChar(Chr(C)) 
    End Function 

    Private Function IsPrintChar(ByVal C As Char) As Boolean 

    TempLogStart() 
    TempLogStop() 
    Return IsPrintChar(C.ToString) 
    End Function 

    Private Function IsPrintChar(ByVal C As String) As Boolean 

    TempLogStart() 
    If System.Text.RegularExpressions.Regex.IsMatch(C, "[^\t\n\r\f\v]") Then 
     Return True 
    Else 
     Return False 
    End If 
    TempLogStop() 
    End Function 

    Private Sub clsCustomAutoCompleteTextbox_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.GotFocus 

    TempLogStart() 
    If Not Me.SuspendFocus AndAlso Me.myShowAutoCompleteOnFocus AndAlso Me.myForm.Visible = False Then 
     Call Me.ShowAutoComplete() 
    End If 
    TempLogStop() 
    End Sub 

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

    TempLogStart() 
    If Not SelectItem(e.KeyCode) Then 
     If e.KeyCode = Keys.Up Then 
     If myLbox.SelectedIndex > 0 Then 
      Call MoveLBox(myLbox.SelectedIndex - 1) 
     End If 
     ElseIf e.KeyCode = Keys.Down Then 
     Call MoveLBox(myLbox.SelectedIndex + 1) 
     End If 
    End If 
    TempLogStop() 
    End Sub 

    Shadows Sub SelectAll() 

    End Sub 

    Private Sub MoveLBox(ByVal Index As Integer) 

    TempLogStart() 
    Try 
     If Index > myLbox.Items.Count - 1 Then 
     Index = myLbox.Items.Count - 1 
     End If 

     myLbox.SelectedIndex = Index 
    Catch ex As Exception 

    End Try 
    TempLogStop() 
    End Sub 

    Private Sub clsCustomAutoCompleteTextbox_Leave(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Leave 

    TempLogStart() 
    Call DoHide(sender, e) 
    TempLogStop() 
    End Sub 

    Private Sub clsCustomAutoCompleteTextbox_LostFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.LostFocus 

    TempLogStart() 
    Call DoHide(sender, e) 
    TempLogStop() 
    End Sub 

    Private Sub clsCustomAutoCompleteTextbox_Move(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Move 

    TempLogStart() 
    Call MoveDrop() 
    TempLogStop() 
    End Sub 

    Private Sub clsCustomAutoCompleteTextbox_ParentChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.ParentChanged 

    TempLogStart() 
    myParentForm = GetParentForm(Me) 
    TempLogStop() 
    End Sub 

    Private Sub HideTimer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles HideTimer.Tick 

    TempLogStart() 
    Call MoveDrop() 
    Call DoHide(sender, e) 

    Static Cnt As Integer = 0 

    Cnt += 1 

    If Cnt > 300 Then 
     If Not AppHasFocus() Then 
     Call DoHideAuto() 
     End If 

     Cnt = 0 
    End If 
    TempLogStop() 
    End Sub 

    Public Overrides Property SelectedText() As String 
    Get 
     Return MyBase.SelectedText 
    End Get 
    Set(ByVal value As String) 
     MyBase.SelectedText = value 
    End Set 
    End Property 

    Public Overrides Property SelectionLength() As Integer 
    Get 
     Return MyBase.SelectionLength 
    End Get 
    Set(ByVal value As Integer) 
     MyBase.SelectionLength = value 
    End Set 
    End Property 

    Private Sub myLbox_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles myLbox.Click 


    End Sub 

    Private Sub myLbox_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles myLbox.DoubleClick 

    End Sub 

    Private Function SelectItem(Optional ByVal Key As Keys = Keys.None, _ 
         Optional ByVal SingleClick As Boolean = False, _ 
         Optional ByVal DoubleClick As Boolean = False) As Boolean 


    TempLogStart() 
    Dim DoSelect As Boolean = True 
    Dim Meth As SelectOptions 
    Static LastItem As Integer = -1 
    Select Case True 
     Case Me.mySelectionMethods And SelectOptions.OnEnterPress AndAlso Key = Keys.Enter 
     Meth = SelectOptions.OnEnterPress 
     Case Me.mySelectionMethods And SelectOptions.OnRightArrow AndAlso Key = Keys.Right 
     Meth = SelectOptions.OnRightArrow 
     Case Me.mySelectionMethods And SelectOptions.OnTabPress AndAlso Key = Keys.Tab 
     Meth = SelectOptions.OnTabPress 
     Case Me.mySelectionMethods And SelectOptions.OnSingleClick AndAlso SingleClick 
     Meth = SelectOptions.OnSingleClick 
     Case Me.mySelectionMethods And SelectOptions.OnDoubleClick AndAlso DoubleClick 
     Meth = SelectOptions.OnDoubleClick 
     'Case Me.mySelectionMethods And SelectOptions.OnItemChange AndAlso (LastItem <> myLbox.SelectedIndex) 
     Case Else 
     DoSelect = False 
    End Select 
    LastItem = myLbox.SelectedIndex 
    If DoSelect Then 
     Call DoSelectItem(Meth) 
    End If 
    TempLogStop() 

    Return DoSelect 
    End Function 

    Private Sub DoSelectItem(ByVal Method As SelectOptions) 

    TempLogStart() 
    If Me.myLbox.Items.Count > 0 AndAlso Me.myLbox.SelectedIndex > -1 Then 
     Dim Value As String = Me.myLbox.SelectedItem.ToString 

     Dim Orig As String = Me.Text 

     Me.Text = Value 

     If mySelectTextAfterItemSelect Then 
     Try 
      Me.SelectionStart = Orig.Length 
      Me.SelectionLength = Value.Length - Orig.Length 
     Catch ex As Exception 
     End Try 
     Else 
     'Me.SelectionStart = Me.Text.Length 
     'Me.SelectionLength = 0 
     End If 

     RaiseEvent ItemSelected(Me, New clsItemSelectedEventArgs(Me.myLbox.SelectedIndex, Method, Value)) 

     Call Me.DoHideAuto() 
    End If 
    TempLogStop() 
    End Sub 

    Public Class clsItemSelectedEventArgs 
    Private myIndex As Integer 
    Private myMethod As SelectOptions 
    Private myItemText As String 

    Public Property ItemText() As Boolean 
     Get 
     Return myItemText 
     End Get 
     Set(ByVal value As Boolean) 
     myItemText = value 
     End Set 
    End Property 

    Public Property Method() As SelectOptions 
     Get 
     Return myMethod 
     End Get 
     Set(ByVal value As SelectOptions) 
     myMethod = value 
     End Set 
    End Property 

    Public Property Index() As Integer 
     Get 
     Return myIndex 
     End Get 
     Set(ByVal value As Integer) 
     myIndex = value 
     End Set 
    End Property 

    Sub New() 

    End Sub 
    Sub New(ByVal Index As Integer, ByVal Method As SelectOptions, ByVal ItemText As String) 
     myIndex = Index 
     myMethod = Method 
     myItemText = ItemText 
    End Sub 
    End Class 

    Private Sub myLbox_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles myLbox.GotFocus 

    TempLogStart() 
    Call DFocus() 
    TempLogStop() 
    End Sub 

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

    TempLogStart() 
    Call SelectItem(e.KeyCode) 
    TempLogStop() 
    End Sub 

    Private Sub ProcessKeyEvents(ByVal e As KeyEventArgs) 

    TempLogStart() 
    Select Case e.KeyCode 
     Case Is >= Keys.A And e.KeyCode <= Keys.Z 
     MyBase.OnKeyUp(e) 
     Case Keys.Back 

     Case Keys.Enter 

     Case Keys.Left, Keys.Right, Keys.Up, Keys.Down 

     Case Is >= Keys.NumPad0 And e.KeyCode <= Keys.NumPad9, Is >= Keys.D0 And e.KeyCode <= Keys.D9 

    End Select 
    TempLogStop() 
    End Sub 

    Private Sub myLbox_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles myLbox.KeyPress 
    If IsPrintChar(e.KeyChar) Then 
     'Me.OnKeyPress(e) 
     'Call MoveDrop() 
    End If 
    TempLogStop() 
    End Sub 

    Private Sub myLbox_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles myLbox.KeyUp 
    If IsPrintChar(e.KeyValue) Then 
     'Me.OnKeyUp(e) 
     'Call MoveDrop() 
    End If 
    TempLogStop() 
    End Sub 

    Private Sub myLbox_LostFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles myLbox.LostFocus 

    TempLogStart() 
    Call DoHide(sender, e) 
    TempLogStop() 
    End Sub 

    Private Sub myLbox_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles myLbox.MouseClick 

    TempLogStart() 
    'If e.Button <> Windows.Forms.MouseButtons.None Then 
    Call SelectItem(SingleClick:=True) 

    'End If 
    TempLogStop() 
    End Sub 

    Private Sub myLbox_MouseDoubleClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles myLbox.MouseDoubleClick 

    TempLogStart() 
    'If e.Button <> Windows.Forms.MouseButtons.None Then 
    Call SelectItem(DoubleClick:=True) 

    'End If 
    TempLogStop() 
    End Sub 

    Private Sub myForm_Deactivate(ByVal sender As Object, ByVal e As System.EventArgs) Handles myForm.Deactivate 

    TempLogStart() 
    Call TryHideFormWindowsDeactivated() 
    TempLogStop() 
    End Sub 

    Private Sub myParentForm_Deactivate(ByVal sender As Object, ByVal e As System.EventArgs) Handles myParentForm.Deactivate 

    TempLogStart() 
    Call TryHideFormWindowsDeactivated() 
    TempLogStop() 
    End Sub 

    Private Sub FocusTimer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles FocusTimer.Tick 

    TempLogStart() 
    Me.Focus() 
    TempLogStop() 
    End Sub 

    Public Sub New() 

    End Sub 

    Private Sub myLbox_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles myLbox.MouseDown 
    myLbox_MouseClick(sender, e) 
    End Sub 
End Class 

#End Region 
15

這裏是C#版本。它有很多選擇。

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 

namespace WindowsFormsApplication1 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      this.Load += new EventHandler(this.Form1_Load); 

      InitializeComponent(); 
     } 

    private clsCustomAutoCompleteTextbox ClsCustomAutoCompleteTextbox1 = null; 

    private List<string> MasterList = new List<string>(); 

    public void Form1_Load(object sender, System.EventArgs e) { 
     this.ClsCustomAutoCompleteTextbox1 = new clsCustomAutoCompleteTextbox(); 

     this.ClsCustomAutoCompleteTextbox1.AutoCompleteFormBorder = System.Windows.Forms.FormBorderStyle.None; 

     this.ClsCustomAutoCompleteTextbox1.AutoCompleteList = null; 
     this.ClsCustomAutoCompleteTextbox1.Location = new System.Drawing.Point(27, 57); 
     this.ClsCustomAutoCompleteTextbox1.Name = "clsCustomAutoCompleteTextbox1"; 
     this.ClsCustomAutoCompleteTextbox1.OnEnterSelect = true; 
     this.ClsCustomAutoCompleteTextbox1.SelectionMethods = clsCustomAutoCompleteTextbox.SelectOptions.OnEnterSingleClick; 
     this.ClsCustomAutoCompleteTextbox1.SelectTextAfterItemSelect = true; 
     this.ClsCustomAutoCompleteTextbox1.ShowAutoCompleteOnFocus = false; 
     this.ClsCustomAutoCompleteTextbox1.Size = new System.Drawing.Size(232, 20); 
     this.ClsCustomAutoCompleteTextbox1.TabIndex = 0; 

     this.Controls.Add(this.ClsCustomAutoCompleteTextbox1); 

     this.ClsCustomAutoCompleteTextbox1.BeforeDisplayingAutoComplete += 
      new EventHandler<clsCustomAutoCompleteTextbox.clsAutoCompleteEventArgs>(BeforeDisplayingAutoComplete); 

     List<string> L; 
     L = new List<string>(); 
     L.Add("123123 - Bob"); 
     L.Add("534543 - Sally"); 
     L.Add("123123 - George"); 
     L.Add("34213 - Happy"); 
     MasterList = L; 
     this.ClsCustomAutoCompleteTextbox1.AutoCompleteList = L; 
    } 

    private void BeforeDisplayingAutoComplete(object sender, clsCustomAutoCompleteTextbox.clsAutoCompleteEventArgs e) { 
     string Name = this.ClsCustomAutoCompleteTextbox1.Text.ToLower(); 
     List<string> Display = new List<string>(); 
     foreach (string Str in MasterList) { 
      if ((Str.ToLower().IndexOf(Name) > -1)) { 
       Display.Add(Str); 
      } 
     } 
     e.AutoCompleteList = Display; 
     e.SelectedIndex = 0; 
    } 
} 
public class clsCustomAutoCompleteTextbox : TextBox 
{ 
    private bool First = true; 

    private object sender; 

    private clsAutoCompleteEventArgs e; 

    public List<string> test = new List<string>(); 

    public int Tabs = 0; 

    private int mSelStart; 

    private int mSelLength; 

    private List<string> myAutoCompleteList = new List<string>(); 

    private ListBox myLbox = new ListBox(); 

    private Form myForm = new Form(); 

    private Form myParentForm; 

    private bool DontHide = false; 

    private bool SuspendFocus = false; 

    private clsAutoCompleteEventArgs Args; 

    private Timer HideTimer = new Timer(); 

    private Timer FocusTimer = new Timer(); 

    private bool myShowAutoCompleteOnFocus; 

    private System.Windows.Forms.FormBorderStyle myAutoCompleteFormBorder = FormBorderStyle.None; 

    private bool myOnEnterSelect; 

    private int LastItem; 

    private SelectOptions mySelectionMethods = (SelectOptions.OnDoubleClick | SelectOptions.OnEnterPress); 

    private bool mySelectTextAfterItemSelect = true; 

    private List<string> value; 

    private int Cnt = 0; 

    public bool SelectTextAfterItemSelect 
    { 
     get 
     { 
      return mySelectTextAfterItemSelect; 
     } 
     set 
     { 
      mySelectTextAfterItemSelect = value; 
     } 
    } 

    [System.ComponentModel.Browsable(false)] 
    public SelectOptions SelectionMethods 
    { 
     get 
     { 
      return mySelectionMethods; 
     } 
     set 
     { 
      mySelectionMethods = value; 
     } 
    } 

    public bool OnEnterSelect 
    { 
     get 
     { 
      return myOnEnterSelect; 
     } 
     set 
     { 
      myOnEnterSelect = value; 
     } 
    } 

    public System.Windows.Forms.FormBorderStyle AutoCompleteFormBorder 
    { 
     get 
     { 
      return myAutoCompleteFormBorder; 
     } 
     set 
     { 
      myAutoCompleteFormBorder = value; 
     } 
    } 

    public bool ShowAutoCompleteOnFocus 
    { 
     get 
     { 
      return myShowAutoCompleteOnFocus; 
     } 
     set 
     { 
      myShowAutoCompleteOnFocus = value; 
     } 
    } 

    public ListBox Lbox 
    { 
     get 
     { 
      return myLbox; 
     } 
    } 

    public List<string> AutoCompleteList { get; set; } 

    public event EventHandler<clsAutoCompleteEventArgs> BeforeDisplayingAutoComplete; 

    public event EventHandler<clsItemSelectedEventArgs> ItemSelected; 

    public enum SelectOptions 
    { 
     None = 0, 

     OnEnterPress = 1, 

     OnSingleClick = 2, 

     OnDoubleClick = 4, 

     OnTabPress = 8, 

     OnRightArrow = 16, 

     OnEnterSingleClick = 3, 

     OnEnterSingleDoubleClicks = 7, 

     OnEnterDoubleClick = 5, 

     OnEnterTab = 9, 
    } 

    public class clsAutoCompleteEventArgs : EventArgs 
    { 

     private List<string> myAutoCompleteList; 

     private bool myCancel; 

     private int mySelectedIndex; 

     private List<string> value; 

     public int SelectedIndex 
     { 
      get 
      { 
       return mySelectedIndex; 
      } 
      set 
      { 
       mySelectedIndex = value; 
      } 
     } 

     public bool Cancel 
     { 
      get 
      { 
       return myCancel; 
      } 
      set 
      { 
       myCancel = value; 
      } 
     } 
     public List<string> AutoCompleteList { get; set; } 
    } 

    public override string SelectedText 
    { 
     get 
     { 
      return base.SelectedText; 
     } 
     set 
     { 
      base.SelectedText = value; 
     } 
    } 

    public override int SelectionLength 
    { 
     get 
     { 
      return base.SelectionLength; 
     } 
     set 
     { 
      base.SelectionLength = value; 
     } 
    } 

    public clsCustomAutoCompleteTextbox() 
    { 
     HideTimer.Tick += new EventHandler(HideTimer_Tick); 
     FocusTimer.Tick += new EventHandler(FocusTimer_Tick); 

     myLbox.Click += new EventHandler(myLbox_Click); 
     myLbox.DoubleClick += new EventHandler(myLbox_DoubleClick); 
     myLbox.GotFocus += new EventHandler(myLbox_GotFocus); 
     myLbox.KeyDown += new KeyEventHandler(myLbox_KeyDown); 

     myLbox.KeyUp += new KeyEventHandler(myLbox_KeyUp); 
     myLbox.LostFocus += new EventHandler(myLbox_LostFocus); 
     myLbox.MouseClick += new MouseEventHandler(myLbox_MouseClick); 
     myLbox.MouseDoubleClick += new MouseEventHandler(myLbox_MouseDoubleClick); 
     myLbox.MouseDown += new MouseEventHandler(myLbox_MouseDown); 


     this.GotFocus += new EventHandler(clsCustomAutoCompleteTextbox_GotFocus); 
     this.KeyDown += new KeyEventHandler(clsCustomAutoCompleteTextbox_KeyDown); 
     this.Leave += new EventHandler(clsCustomAutoCompleteTextbox_Leave); 
     this.LostFocus += new EventHandler(clsCustomAutoCompleteTextbox_LostFocus); 
     this.Move += new EventHandler(clsCustomAutoCompleteTextbox_Move); 
     this.ParentChanged += new EventHandler(clsCustomAutoCompleteTextbox_ParentChanged); 


    } 

    override protected void OnKeyUp(System.Windows.Forms.KeyEventArgs e) 
    { 


     base.OnKeyUp(e); 
     ShowOnChar(new string(((char)(e.KeyValue)),1)); 
    } 

    private void ShowOnChar(string C) 
    { 


     if (IsPrintChar(C)) 
     { 
      this.ShowAutoComplete(); 
     } 
    } 

    private bool IsPrintChar(int C) 
    { 


     return IsPrintChar(((char)(C))); 
    } 

    private bool IsPrintChar(byte C) 
    { 


     return IsPrintChar(((char)(C))); 
    } 

    private bool IsPrintChar(char C) 
    { 


     return IsPrintChar(C.ToString()); 
    } 

    private bool IsPrintChar(string C) 
    { 

     if (System.Text.RegularExpressions.Regex.IsMatch(C, "[^\\t\\n\\r\\f\\v]")) 
     { 
      return true; 
     } 
     else 
     { 
      return false; 
     } 

    } 

    private void clsCustomAutoCompleteTextbox_GotFocus(object sender, System.EventArgs e) 
    { 

     if ((!this.SuspendFocus 
        && (this.myShowAutoCompleteOnFocus 
        && (this.myForm.Visible == false)))) 
     { 
      this.ShowAutoComplete(); 
     } 

    } 

    private void clsCustomAutoCompleteTextbox_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) 
    { 

     if (!SelectItem(e.KeyCode, false, false)) 
     { 
      if ((e.KeyCode == Keys.Up)) 
      { 
       if ((myLbox.SelectedIndex > 0)) 
       { 
        MoveLBox((myLbox.SelectedIndex - 1)); 
       } 
      } 
      else if ((e.KeyCode == Keys.Down)) 
      { 
       MoveLBox((myLbox.SelectedIndex + 1)); 
      } 
     } 

    } 

    new void SelectAll() 
    { 
    } 

    private void MoveLBox(int Index) 
    { 

     try 
     { 
      if ((Index 
         > (myLbox.Items.Count - 1))) 
      { 
       Index = (myLbox.Items.Count - 1); 
      } 
      myLbox.SelectedIndex = Index; 
     } 
     catch 
     { 
     } 

    } 

    private void clsCustomAutoCompleteTextbox_Leave(object sender, System.EventArgs e) 
    { 

     DoHide(sender, e); 

    } 

    private void clsCustomAutoCompleteTextbox_LostFocus(object sender, System.EventArgs e) 
    { 

     DoHide(sender, e); 

    } 

    private void clsCustomAutoCompleteTextbox_Move(object sender, System.EventArgs e) 
    { 

     MoveDrop(); 

    } 

    private void clsCustomAutoCompleteTextbox_ParentChanged(object sender, System.EventArgs e) 
    { 

     if (myParentForm != null) myParentForm.Deactivate -= new EventHandler(myParentForm_Deactivate); 
     myParentForm = GetParentForm(this); 
     if (myParentForm != null) myParentForm.Deactivate += new EventHandler(myParentForm_Deactivate); 
    } 

    private void HideTimer_Tick(object sender, System.EventArgs e) 
    { 

     MoveDrop(); 
     DoHide(sender, e); 
     Cnt++; 
     if ((Cnt > 300)) 
     { 
      if (!AppHasFocus("")) 
      { 
       DoHideAuto(); 
      } 
      Cnt = 0; 
     } 

    } 

    private void myLbox_Click(object sender, System.EventArgs e) 
    { 
    } 

    private void myLbox_DoubleClick(object sender, System.EventArgs e) 
    { 
    } 

    private bool SelectItem(Keys Key, bool SingleClick) 
    { 
     return SelectItem(Key, SingleClick, false); 
    } 

    private bool SelectItem(Keys Key) 
    { 
     return SelectItem(Key, false, false); 
    } 

    private bool SelectItem(Keys Key, bool SingleClick, bool DoubleClick) 
    { 

     // Warning!!! Optional parameters not supported 
     // Warning!!! Optional parameters not supported 
     // Warning!!! Optional parameters not supported 
     bool DoSelect = true; 
     SelectOptions Meth = SelectOptions.None; 
     LastItem = -1; 

     if (((this.mySelectionMethods & SelectOptions.OnEnterPress) > 0) && (Key == Keys.Enter)) 
     { 
      Meth = SelectOptions.OnEnterPress; 
     } 
     else if (((this.mySelectionMethods & SelectOptions.OnRightArrow) > 0) && Key == Keys.Right) 
     { 
      Meth = SelectOptions.OnRightArrow; 
     } 
     else if (((this.mySelectionMethods & SelectOptions.OnTabPress) > 0) && Key == Keys.Tab) 
     { 
      Meth = SelectOptions.OnTabPress; 
     } 
     else if (((this.mySelectionMethods & SelectOptions.OnSingleClick) > 0) && SingleClick) 
     { 
      Meth = SelectOptions.OnEnterPress; 
     } 
     else if (((this.mySelectionMethods & SelectOptions.OnDoubleClick) > 0) && DoubleClick) 
     { 
      Meth = SelectOptions.OnEnterPress; 
     } 
     else 
     { 
      DoSelect = false; 
     } 

     LastItem = myLbox.SelectedIndex; 
     if (DoSelect) 
     { 
      DoSelectItem(Meth); 
     } 

     return DoSelect; 
    } 
    public class clsItemSelectedEventArgs : EventArgs 
    { 

     private int myIndex; 

     private SelectOptions myMethod; 

     private string myItemText; 

     public clsItemSelectedEventArgs() 
     { 
     } 

     public clsItemSelectedEventArgs(int Index, SelectOptions Method, string ItemText) 
     { 
      myIndex = Index; 
      myMethod = Method; 
      myItemText = ItemText; 
     } 

     public string ItemText 
     { 
      get 
      { 
       return myItemText; 
      } 
      set 
      { 
       myItemText = value; 
      } 
     } 

     public SelectOptions Method 
     { 
      get 
      { 
       return myMethod; 
      } 
      set 
      { 
       myMethod = value; 
      } 
     } 

     public int Index 
     { 
      get 
      { 
       return myIndex; 
      } 
      set 
      { 
       myIndex = value; 
      } 
     } 
    } 

     [System.Runtime.InteropServices.DllImport("user32.dll")] 
     static extern IntPtr GetForegroundWindow(); 

     [System.Runtime.InteropServices.DllImport("user32.dll")] 
     static extern int GetWindowThreadProcessId(IntPtr hWnd, ref int ProcessID); 

     private bool AppHasFocus(string ExeNameWithoutExtension) 
     { 
      bool Out = false; 
      // Warning!!! Optional parameters not supported 
      int PID = 0; 

      if ((ExeNameWithoutExtension == "")) 
      { 
       ExeNameWithoutExtension = System.Diagnostics.Process.GetCurrentProcess().ProcessName; 
      } 
      IntPtr activeHandle = GetForegroundWindow(); 
      GetWindowThreadProcessId(activeHandle, ref PID); 
      if ((PID > 0)) 
      { 
       // For Each p As Process In Process.GetProcessesByName(ExeNameWithoutExtension) 
       if ((PID == System.Diagnostics.Process.GetCurrentProcess().Id)) 
       { 
        Out = true; 
       } 
       // Next 
      } 

      return Out; 
     } 

     private void SaveSelects() 
     { 
      this.mSelStart = this.SelectionStart; 
      this.mSelLength = this.SelectionLength; 
     } 

     private void LoadSelects() 
     { 
      this.SelectionStart = this.mSelStart; 
      this.SelectionLength = this.mSelLength; 
     } 

     private void ShowAutoComplete() 
     { 

      Args = new clsAutoCompleteEventArgs(); 
      // With... 
      Args.Cancel = false; 
      Args.AutoCompleteList = this.myAutoCompleteList; 
      if ((myLbox.SelectedIndex == -1)) 
      { 
       Args.SelectedIndex = 0; 
      } 
      else 
      { 
       Args.SelectedIndex = myLbox.SelectedIndex; 
      } 

      if (BeforeDisplayingAutoComplete != null) BeforeDisplayingAutoComplete(this, Args); 
      this.myAutoCompleteList = Args.AutoCompleteList; 
      // If Me.myAutoCompleteList IsNot Nothing AndAlso Me.myAutoCompleteList.Count - 1 < Args.SelectedIndex Then 
      // Args.SelectedIndex = Me.myAutoCompleteList.Count - 1 
      // End If 
      if ((!Args.Cancel && (Args.AutoCompleteList != null) && Args.AutoCompleteList.Count > 0)) 
      { 
       DoShowAuto(); 
      } 
      else 
      { 
       DoHideAuto(); 
      } 

     } 

     private void DoShowAuto() 
     { 
      SaveSelects(); 

      myLbox.BeginUpdate(); 
      try 
      { 
       myLbox.Items.Clear(); 
       myLbox.Items.AddRange(this.myAutoCompleteList.ToArray()); 
       this.MoveLBox(Args.SelectedIndex); 
      } 
      catch (Exception ex) 
      { 
      } 
      myLbox.EndUpdate(); 
      myParentForm = GetParentForm(this); 
      if (myParentForm != null) 
      { 
       myLbox.Name = ("mmmlbox" + DateTime.Now.Millisecond); 
       if ((myForm.Visible == false)) 
       { 
        myForm.Font = this.Font; 
        myLbox.Font = this.Font; 
        myLbox.Visible = true; 
        myForm.Visible = false; 
        myForm.ControlBox = false; 
        myForm.Text = ""; 
        if (First) 
        { 
         myForm.Width = this.Width; 
         myForm.Height = 200; 
        } 
        First = false; 
        if (!myForm.Controls.Contains(myLbox)) 
        { 
         myForm.Controls.Add(myLbox); 
        } 
        myForm.FormBorderStyle = FormBorderStyle.None; 
        myForm.ShowInTaskbar = false; 
        // With... 
        myLbox.Dock = DockStyle.Fill; 
        myLbox.SelectionMode = SelectionMode.One; 
        // Frm.Controls.Add(myLbox) 
        DontHide = true; 
        SuspendFocus = true; 
        myForm.TopMost = true; 
        myForm.FormBorderStyle = this.myAutoCompleteFormBorder; 
        myForm.BringToFront(); 
        MoveDrop(); 
        myForm.Visible = true; 
        myForm.Show(); 
        MoveDrop(); 
        HideTimer.Interval = 10; 
        this.Focus(); 
        SuspendFocus = false; 
        HideTimer.Enabled = true; 
        DontHide = false; 
        LoadSelects(); 
       } 
      } 

     } 

     void MoveDrop() 
     { 

      Point Pnt = new Point(this.Left, (this.Top 
          + (this.Height + 2))); 
      Point ScreenPnt = this.PointToScreen(new Point(-2, this.Height)); 
      // Dim FrmPnt As Point = Frm.PointToClient(ScreenPnt) 
      if (myForm != null) 
      { 
       myForm.Location = ScreenPnt; 
       // myForm.BringToFront() 
       // myForm.Focus() 
       // myLbox.Focus() 
       // Me.Focus() 
      } 

     } 

     void DoHide(object sender, EventArgs e) 
     { 

      HideAuto(); 

     } 

     private void DFocus(int Delay) 
     { 

      // Warning!!! Optional parameters not supported 
      FocusTimer.Interval = Delay; 
      FocusTimer.Start(); 

     } 

     private void DFocus() 
     { 
      DFocus(10); 
     } 

     private void DoHideAuto() 
     { 

      myForm.Hide(); 
      HideTimer.Enabled = false; 
      FocusTimer.Enabled = false; 

     } 

     private void HideAuto() 
     { 

      if ((myForm.Visible && HasLostFocus())) 
      { 
       DoHideAuto(); 
      } 

     } 

     private bool HasLostFocus() 
     { 

      bool Out = false; 
      if (this.myForm == null || myForm.ActiveControl != this.myLbox) 
      { 
       Out = true; 
      } 
      if (this.myParentForm == null || this.myParentForm.ActiveControl != this) 
      { 
       Out = true; 
      } 

      return Out; 
     } 

     private Form GetParentForm(Control InCon) 
     { 

      Control TopCon = FindTopParent(InCon); 
      Form Out = null; 
      if ((TopCon is Form)) 
      { 
       Out = ((Form)(TopCon)); 
      } 

      return Out; 
     } 

     private Control FindTopParent(Control InCon) 
     { 

      Control Out; 
      if ((InCon.Parent == null)) 
      { 
       Out = InCon; 
      } 
      else 
      { 
       Out = FindTopParent(InCon.Parent); 
      } 

      return Out; 
     } 

     private void DoSelectItem(SelectOptions Method) 
     { 

      if (((this.myLbox.Items.Count > 0) 
         && (this.myLbox.SelectedIndex > -1))) 
      { 
       string Value = this.myLbox.SelectedItem.ToString(); 
       string Orig = this.Text; 
       this.Text = Value; 
       if (mySelectTextAfterItemSelect) 
       { 
        try 
        { 
         this.SelectionStart = Orig.Length; 
         this.SelectionLength = (Value.Length - Orig.Length); 
        } 
        catch (Exception ex) 
        { 
        } 
       } 
       else 
       { 
        // Me.SelectionStart = Me.Text.Length 
        // Me.SelectionLength = 0 
       } 

       clsItemSelectedEventArgs a; 
       a = new clsItemSelectedEventArgs(); 
       a.Index = this.myLbox.SelectedIndex; 
       a.Method = Method; 
       a.ItemText = Value; 

       if (ItemSelected != null) ItemSelected(this, a); 

       //ItemSelected(this, new clsItemSelectedEventArgs(this.myLbox.SelectedIndex, Method, Value)); 
       this.DoHideAuto(); 
      } 

     } 

     private void myLbox_GotFocus(object sender, System.EventArgs e) 
     { 

      DFocus(); 

     } 

     private void myLbox_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) 
     { 

      SelectItem(e.KeyCode); 

     } 

     private void ProcessKeyEvents(KeyEventArgs e) 
     { 


       if ((e.KeyCode >= Keys.A) && (e.KeyCode <= Keys.Z)) 
        base.OnKeyUp(e); 


       //Keys.Back; 
       //Keys.Enter; 
       //Keys.Left; 
       //Keys.Right; 
       //Keys.Up; 
       //Keys.Down; 
       //(Keys.NumPad0 & (e.KeyCode <= Keys.NumPad9)); 
       //(Keys.D0 & (e.KeyCode <= Keys.D9)); 


     } 

     private void myLbox_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) 
     { 
      if (IsPrintChar(e.KeyChar)) 
      { 
       // Me.OnKeyPress(e) 
       // Call MoveDrop() 
      } 

     } 

     private void myLbox_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e) 
     { 
      if (IsPrintChar(e.KeyValue)) 
      { 
       // Me.OnKeyUp(e) 
       // Call MoveDrop() 
      } 

     } 

     private void myLbox_LostFocus(object sender, System.EventArgs e) 
     { 

      DoHide(sender, e); 

     } 

     private void myLbox_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e) 
     { 

      // If e.Button <> Windows.Forms.MouseButtons.None Then 
      SelectItem(Keys.None,true); 
      // End If 

     } 

     private void myLbox_MouseDoubleClick(object sender, System.Windows.Forms.MouseEventArgs e) 
     { 

      // If e.Button <> Windows.Forms.MouseButtons.None Then 
      SelectItem(Keys.None, false, true); 
      // End If 

     } 

     private void myForm_Deactivate(object sender, System.EventArgs e) 
     { 


     } 

     private void myParentForm_Deactivate(object sender, System.EventArgs e) 
     { 


     } 

     private void FocusTimer_Tick(object sender, System.EventArgs e) 
     { 

      this.Focus(); 

     } 

     private void myLbox_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) 
     { 
      myLbox_MouseClick(sender, e); 
     } 
    } 
} 
+0

你知道如果這個代碼將處理上下在我預料的方式箭頭按鍵,通過向上或向下移動選擇?這似乎並沒有爲我工作,但也許我「打破」了原來的職位工作。 – 2012-06-12 14:53:40

2

我不知道這是一種選擇,但是,例如,你可以做這樣的事情:

private void Main_Load(object sender, EventArgs e) 
    { 
     DataTable dt = new DataTable(); 
     dt.Columns.Add("colCustomers", typeof(string)); 
     dt.Rows.Add(new object[] { "1 John" }); 
     dt.Rows.Add(new object[] { "2 Kate" }); 
     dt.Rows.Add(new object[] { "3 Jill" }); 

     comboBox1.DataSource = dt.DefaultView; //allows us to filter the results 
     comboBox1.DisplayMember = "Col1"; 
    } 

    private void comboBox1_TextChanged(object sender, EventArgs e) 
    { 
     if (comboBox1.SelectedIndex == -1) 
     { 
      dt.DefaultView.RowFilter = "colCustomers LIKE '%" + comboBox1.Text + "%'"; 
     } 
    } 

Ofcourse,您還可以使用搜索&定位,而不是過濾,而是因爲可能有很多客戶,我認爲只留下匹配的客戶會更好。當用戶刪除他的條目時,它應該再次顯示每個人。代碼可能會受益於您的需求的一些調整,但你必須嘗試想出你想要的。

-2

這裏是我的代碼爲一個數據綁定組合框(在我的情況下一個Access數據庫)。 您將一個組合框和列表框添加到窗體。然後,用我下面的代碼作爲參考,因爲它表明:

  1. 如何更新數據綁定組合框
  2. 添加事件處理程序,從而 當您在組合框中使用箭頭鍵使其通過 結果列表框。
  3. 僅當自上次按鍵時間過去500ms後,才使用計時器將數據庫查詢限制爲 。

我確定有更好的方法來做這些事情。此代碼「適合我」。批評表示讚賞。

#region AutoComplete Organization Box 

    System.Windows.Forms.Timer mOrganizationTextChangedTimer = null; 
    void organizationComboBox_TextChanged(object sender, System.EventArgs e) 
    { 
     if (mOrganizationTextChangedTimer == null) 
     { 
      mOrganizationTextChangedTimer = new System.Windows.Forms.Timer(); 
      mOrganizationTextChangedTimer.Interval = 500; 
      mOrganizationTextChangedTimer.Tick += new EventHandler(mOrganizationTextChangedTimer_Tick); 
     } 
     mOrganizationTextChangedTimer.Enabled = true; 
    } 

    void mOrganizationTextChangedTimer_Tick(object sender, EventArgs e) 
    { 
     mOrganizationTextChangedTimer.Enabled = false; 
     UpdateOrganizationNameAutocompleteResults(comboBoxOrganizationName.Text);  
    } 

    void UpdateOrganizationNameAutocompleteResults(string pSearchString) 
    { 
     listBoxOrganizationAutocompleteResults.Items.Clear(); 
     if (comboBoxOrganizationName.Text.Length == 0) 
     { 
      HideOrganizationNameAutocompleteResults(); 
      return; 
     } 

     // Added a custom query to search our database and return results that match. The query uses UCase on the columns. 
     allertDataSet3.OrganizationDataTable orgs = organizationTableAdapter.GetDataByOrganizationNameSearchUCase("%" + pSearchString.ToUpper() + "%", "%" + pSearchString.ToUpper() + "%"); 

     foreach(allertDataSet3.OrganizationRow r in orgs) { 
      string longName = r.OrganizationName; 
      listBoxOrganizationAutocompleteResults.Items.Add(longName); 
      listBoxOrganizationAutocompleteResults.Visible = true; 
      listBoxOrganizationAutocompleteResults.BringToFront(); 
     } 

     // This Code block is needed because once you select an organization, the combobox text changes which forces another search. 
     // There is only one result from that search so this hides it when the search result equals the already selected combobox. 
     try { 
      System.Data.DataRowView drv = (System.Data.DataRowView) comboBoxOrganizationName.SelectedItem; 
      allertDataSet3.OrganizationRow orgRow = (allertDataSet3.OrganizationRow)drv.Row; 

      if (listBoxOrganizationAutocompleteResults.Items.Count == 1 && 
       ((string)listBoxOrganizationAutocompleteResults.Items[0]).Equals(orgRow.OrganizationName)) 
      { 
       HideOrganizationNameAutocompleteResults(); 
      } 
     } 
     catch { 
      // do nothing 
     }    
    } 

    void organizationComboBoxAutocompleteResults_SelectedIndexChanged(object sender, System.EventArgs e) 
    { 
     foreach (System.Data.DataRowView drv in comboBoxOrganizationName.Items) 
     { 
      Alertus.Allert.allertDataSet3.OrganizationRow orgRow = (Alertus.Allert.allertDataSet3.OrganizationRow)drv.Row; 
      if (orgRow.OrganizationName.Equals((string) listBoxOrganizationAutocompleteResults.SelectedItem)) 
      { 
       // Prevents it from searching again. 
       comboBoxOrganizationName.TextChanged -= organizationComboBox_TextChanged; 
       comboBoxOrganizationName.SelectedItem = drv; 
       comboBoxOrganizationName.TextChanged += organizationComboBox_TextChanged; 
       HideOrganizationNameAutocompleteResults(); 
       return; 
      } 
     } 

     // This is basically an error... it should have found it. 
     HideOrganizationNameAutocompleteResults(); 
    } 

    void listBoxOrganizationAutocompleteResults_LostFocus(object sender, System.EventArgs e) 
    { 
     HideOrganizationNameAutocompleteResults(); 
    } 

    void HideOrganizationNameAutocompleteResults() 
    { 
     listBoxOrganizationAutocompleteResults.Visible = false; 
    } 

    private void listBoxOrganizationAutocompleteResults_MouseClick(object sender, MouseEventArgs e) 
    { 
     // When mouse is clicked we assume user made a seletion. 
     organizationComboBoxAutocompleteResults_SelectedIndexChanged(null, null); 
    } 

    /// <summary> 
    /// Redirects the Arrow keys to update the selected index in the autocomplete list box. 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="e"></param> 
    private void comboBoxOrganizationName_KeyDown(object sender, KeyEventArgs e) 
    { 
     if (e.KeyCode == Keys.Up) 
     { 
      if (listBoxOrganizationAutocompleteResults.Items.Count >= 1 && listBoxOrganizationAutocompleteResults.Visible) 
      { 
       if (listBoxOrganizationAutocompleteResults.SelectedIndex < 0) 
       { 
        listBoxOrganizationAutocompleteResults.SelectedIndex = 0; 
       } 
       else 
       { 
        listBoxOrganizationAutocompleteResults.SelectedIndex = (listBoxOrganizationAutocompleteResults.SelectedIndex - 1) % listBoxOrganizationAutocompleteResults.Items.Count; 
       } 
      } 
      e.Handled = true; 
     } 
     else if (e.KeyCode == Keys.Down) 
     { 
      if (listBoxOrganizationAutocompleteResults.Items.Count >= 1 && listBoxOrganizationAutocompleteResults.Visible) 
      { 
       if (listBoxOrganizationAutocompleteResults.SelectedIndex < 0) 
       { 

        listBoxOrganizationAutocompleteResults.SelectedIndex = 0; 
       } 
       else 
       { 
        listBoxOrganizationAutocompleteResults.SelectedIndex = (listBoxOrganizationAutocompleteResults.SelectedIndex + 1) % listBoxOrganizationAutocompleteResults.Items.Count; 
       } 
      } 

      e.Handled = true; 
     } 
     else if (e.KeyCode == Keys.Enter) 
     { 
      e.Handled = true; 
      if (listBoxOrganizationAutocompleteResults.Visible) 
      { 
       organizationComboBoxAutocompleteResults_SelectedIndexChanged(null, null); 
      } 
     } 
    } 

    #endregion 

設計師代碼:

// 
    // comboBoxOrganizationName 
    // 
    this.comboBoxOrganizationName.FormattingEnabled = true; 
    this.comboBoxOrganizationName.Location = new System.Drawing.Point(19, 53); 
    this.comboBoxOrganizationName.Name = "comboBoxOrganizationName"; 
    this.comboBoxOrganizationName.Size = new System.Drawing.Size(363, 21); 
    this.comboBoxOrganizationName.TabIndex = 1; 
    this.comboBoxOrganizationName.SelectedIndexChanged += new System.EventHandler(this.comboBoxOrganizationName_SelectedIndexChanged); 
    this.comboBoxOrganizationName.Enter += new System.EventHandler(this.comboBoxOrganizationName_Enter); 
    this.comboBoxOrganizationName.KeyDown += new System.Windows.Forms.KeyEventHandler(this.comboBoxOrganizationName_KeyDown); 
    this.comboBoxOrganizationName.TextChanged += new System.EventHandler(this.organizationComboBox_TextChanged);** 

    // 
      // listBoxOrganizationAutocompleteResults 
      // 
      this.listBoxOrganizationAutocompleteResults.FormattingEnabled = true; 
      this.listBoxOrganizationAutocompleteResults.Location = new System.Drawing.Point(20, 76); 
      this.listBoxOrganizationAutocompleteResults.Name = "listBox1"; 
      this.listBoxOrganizationAutocompleteResults.Size = new System.Drawing.Size(359, 95); 
      this.listBoxOrganizationAutocompleteResults.TabIndex = 19; 
      this.listBoxOrganizationAutocompleteResults.Visible = false; 
      this.listBoxOrganizationAutocompleteResults.MouseClick += new System.Windows.Forms.MouseEventHandler(this.listBoxOrganizationAutocompleteResults_MouseClick); 
      this.listBoxOrganizationAutocompleteResults.Leave += new System.EventHandler(this.listBoxOrganizationAutocompleteResults_LostFocus); 
0

你可以使用這個類:

public partial class MyComboBox : ComboBox 
    { 

     private IList<object> collectionList = null; 

     public MyComboBox() 
     { 
      InitializeComponent(); 
      collectionList = new List<object>(); 

     } 
     public MyComboBox(IContainer container) 
      : this() 
     { 
      container.Add(this); 
     } 

     protected override void OnTextUpdate(EventArgs e) 
     { 
      try 
      { 
       //base.OnTextUpdate(e); 
       IList<object> values = collectionList 
       .Where(x => x.ToString().ToLower().Contains(Text.ToLower())) 
       .ToList(); 

       //Don't use Items.Clear() because the selectionstart resets to Zero 
       while (Items.Count > 0) 
       { 
        Items.RemoveAt(0); 
       } 

       this.Items.AddRange(values.ToArray()); 

       this.DroppedDown = true; 
       Cursor.Current = Cursors.Default; 
      } 
      catch(Exception ex) 
      { 
       SelectedIndex = -1; 
       //MessageBox.Show(ex.Message); 
      } 

     } 

     protected override void OnTextChanged(EventArgs e) 
     { 
      //base.OnTextChanged(e); 
      if (this.Text == string.Empty) 
      { 
       Items.Clear(); 
       this.Items.AddRange(collectionList.ToArray()); 
      } 
     } 

     protected override void OnBindingContextChanged(EventArgs e) 
     { 
      base.OnBindingContextChanged(e); 
      collectionList = this.Items.OfType<object>().ToList(); 
     } 
    } 
相關問題