From 04fd88ea3cf02c564f081f090eedfdd4eacd3d32 Mon Sep 17 00:00:00 2001 From: ChsBuffer <33744752+chsbuffer@users.noreply.github.com> Date: Thu, 10 Sep 2020 17:02:46 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96SearchComboBox?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Netch/Forms/MainForm.Server_Mode.cs | 1 + Netch/Forms/MainForm.cs | 12 ++ NetchLib/SearchComboBox.cs | 205 +++++++++++++++------------- 3 files changed, 126 insertions(+), 92 deletions(-) diff --git a/Netch/Forms/MainForm.Server_Mode.cs b/Netch/Forms/MainForm.Server_Mode.cs index e125fde5..139457dd 100644 --- a/Netch/Forms/MainForm.Server_Mode.cs +++ b/Netch/Forms/MainForm.Server_Mode.cs @@ -65,6 +65,7 @@ namespace Netch.Forms ModeComboBox.Items.Clear(); ModeComboBox.Items.AddRange(Global.Modes.ToArray()); + ModeComboBox.Tag = null; SelectLastMode(); _comboBoxInitialized = comboBoxInitialized; } diff --git a/Netch/Forms/MainForm.cs b/Netch/Forms/MainForm.cs index 7cbde88c..cb670959 100644 --- a/Netch/Forms/MainForm.cs +++ b/Netch/Forms/MainForm.cs @@ -23,6 +23,18 @@ namespace Netch.Forms // 监听电源事件 SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; + ModeComboBox.KeyUp += (sender, args) => + { + switch (args.KeyData) + { + case Keys.Escape: + { + SelectLastMode(); + return; + } + } + }; + CheckForIllegalCrossThreadCalls = false; } diff --git a/NetchLib/SearchComboBox.cs b/NetchLib/SearchComboBox.cs index 2065f000..36379e4e 100644 --- a/NetchLib/SearchComboBox.cs +++ b/NetchLib/SearchComboBox.cs @@ -10,13 +10,48 @@ namespace System.Windows.Forms AutoCompleteMode = AutoCompleteMode.Suggest; } + + private string prevKeyword; + + private string Keyword + { + get => _keyword; + set + { + prevKeyword = _keyword; + if (value == null) + { + _keyword = null; + return; + } + + if (_keyword == value) + { + return; + } + + _keyword = value; + ReevaluateCompletionList(); + } + } + protected override void OnTextChanged(EventArgs e) { try { - if (DesignMode || !string.IsNullOrEmpty(Text) || !Visible) return; - - ResetCompletionList(); + if (string.IsNullOrEmpty(Text)) + { + if (!IsOriginalItems) + ResetCompletionList(); + Keyword = null; + } + else + { + if (AutoFillTag.All(o => o.ToString() != Text)) + { + Keyword = Text; + } + } } finally { @@ -24,53 +59,34 @@ namespace System.Windows.Forms } } - protected override void OnKeyUp(KeyEventArgs e) + + private object[] AutoFillTag { - try + get { - if (DesignMode || e.KeyData == Keys.Up || e.KeyData == Keys.Down) return; - - if (e.KeyData == Keys.Return) + if (Tag == null) { - e.Handled = true; - if (newList.Length > 0 && !newList.Select(o => o.ToString()).Contains(Text)) - { - Text = newList[0].ToString(); - } - - DroppedDown = false; - return; + Tag = Items.Cast().ToArray(); } - ReevaluateCompletionList(); - } - finally - { - base.OnKeyUp(e); + return (object[]) Tag; } } + private bool IsOriginalItems => Items.Count == AutoFillTag.Length; + private void ResetCompletionList() { - _previousSearchTerm = null; + Keyword = null; try { SuspendLayout(); - var originalList = (object[])Tag; - if (originalList == null) - { - Tag = originalList = Items.Cast().ToArray(); - } + if (IsOriginalItems) + return; - if (Items.Count == originalList.Length) return; - - while (Items.Count > 0) - { - Items.RemoveAt(0); - } - - Items.AddRange(originalList); + Items.Clear(); + Items.AddRange(AutoFillTag); } finally { @@ -78,81 +94,86 @@ namespace System.Windows.Forms } } - private string _previousSearchTerm; - private object[] newList; + private static int findFirstDifIndex(string s1, string s2) + { + for (var i = 0; i < Math.Min(s1.Length, s2.Length); i++) + if (s1[i] != s2[i]) + return i; + + return -1; + } + + private object[] _newList; + private string _keyword; + private void ReevaluateCompletionList() { + SuspendLayout(); + var keyword = Keyword.ToLowerInvariant().Trim(); + + var selectionStart = SelectionStart; + if (selectionStart == Text.Length) + { + selectionStart = -1; + } + else + { + selectionStart = findFirstDifIndex(prevKeyword, Keyword); + } + try { - var currentSearchTerm = Text.ToLowerInvariant(); - if (currentSearchTerm == _previousSearchTerm) return; - - _previousSearchTerm = currentSearchTerm; - try + var originalList = AutoFillTag; + if (originalList == null) { - SuspendLayout(); + Tag = originalList = Items.Cast().ToArray(); + } - var originalList = (object[])Tag; - if (originalList == null) + if (string.IsNullOrEmpty(Keyword)) + { + ResetCompletionList(); + return; + } + else + { + _newList = originalList.Where(x => x.ToString().ToLowerInvariant().Contains(keyword)).ToArray(); + } + + if (_newList.Any()) + { + Items.Clear(); + Items.AddRange(_newList.ToArray()); + + if (!DroppedDown) { - Tag = originalList = Items.Cast().ToArray(); - } - - if (string.IsNullOrEmpty(currentSearchTerm)) - { - if (Items.Count == originalList.Length) return; - - newList = originalList; + DroppedDown = true; } else { - newList = originalList.Where(x => x.ToString().ToLowerInvariant().Contains(currentSearchTerm)).ToArray(); + // TODO 预期下拉框高度变长则重新打开下拉框 } - try - { - while (Items.Count > 0) - { - Items.RemoveAt(0); - } - } - catch - { - try - { - Items.Clear(); - } - catch - { - // ignored - } - } - - Items.AddRange(newList.ToArray()); + Cursor.Current = Cursors.Default; } - finally + else { - if (currentSearchTerm.Length >= 2 && !DroppedDown) - { - DroppedDown = true; - Cursor.Current = Cursors.Default; - Text = currentSearchTerm; - Select(currentSearchTerm.Length, 0); - } + DroppedDown = false; + Items.Clear(); + } - if (Items.Count > 0) - { - DroppedDown = false; - DroppedDown = true; - } - - ResumeLayout(true); + if (selectionStart == -1) + { + Select(Text.Length, 0); + } + else + { + Select(selectionStart + 1, 0); } } - catch + finally { - // ignored + ResumeLayout(true); } } } -} +} \ No newline at end of file