From acfc47f018c3fde140658e621e43f1608b0b77a4 Mon Sep 17 00:00:00 2001
From: Patrick Simpson
Date: Thu, 29 Jun 2017 13:37:55 +0200
Subject: [PATCH] Fixed keyboard handling in combo box
---
.../AcaciaZPushPlugin/Controls/KComboBox.cs | 110 +++++++-----------
1 file changed, 43 insertions(+), 67 deletions(-)
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KComboBox.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KComboBox.cs
index 895a3db..38146fe 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KComboBox.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KComboBox.cs
@@ -16,87 +16,49 @@ namespace Acacia.Controls
{
#region Drop-down list
+ ///
+ /// Custom list for the drop-down. Performs a few functions:
+ /// - Prevents grabbing the focus away from the edit when clicked
+ /// - Adds hover highlighting
+ /// - Only commits selection when clicked or externally (through enter in the edit).
+ /// This prevents updating the text and associated filters when scrolling through the combo.
+ ///
private class DropList : ListBox
{
private readonly KComboBox _owner;
- private int _highlightIndex = -1;
+ private int _committedIndex = -1;
public DropList(KComboBox owner)
{
this._owner = owner;
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
- DrawMode = DrawMode.OwnerDrawFixed;
SetStyle(ControlStyles.Selectable, false);
BorderStyle = BorderStyle.None;
}
protected override void OnMouseMove(MouseEventArgs e)
{
- // Use the mouse to highlight the current item
- int newIndex = IndexFromPoint(PointToClient(Cursor.Position));
- if (newIndex != _highlightIndex)
- {
- int oldIndex = _highlightIndex;
- _highlightIndex = newIndex;
-
- // Invalidate the affected items, which may include a previously selected one
- InvalidateItem(oldIndex);
- InvalidateItem(_highlightIndex);
- if (SelectedIndex != oldIndex && SelectedIndex != _highlightIndex)
- InvalidateItem(SelectedIndex);
- }
+ // Perform the select to highlight
+ SelectedIndex = IndexFromPoint(PointToClient(Cursor.Position));
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
- _highlightIndex = -1;
- }
-
- protected override void OnMouseDown(MouseEventArgs e)
- {
- base.OnMouseDown(e);
-
- // Perform the select when the mouse is clicked
- SelectedIndex = IndexFromPoint(PointToClient(Cursor.Position));
+ SelectedIndex = _committedIndex;
}
protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
- _highlightIndex = -1;
+ SelectedIndex = _committedIndex;
}
- private void InvalidateItem(int index)
+ protected override void OnMouseDown(MouseEventArgs e)
{
- if (index < 0 || index >= Items.Count)
- return;
- Invalidate(GetItemRectangle(index));
- }
-
- protected override void OnDrawItem(DrawItemEventArgs e)
- {
- // Create a custom event instance to be able to set the selected state for mouse hover
- DrawItemState state = e.State;
- if (_highlightIndex >= 0)
- {
- state = _highlightIndex == e.Index ? DrawItemState.Selected : DrawItemState.None;
- }
- DrawItemEventArgs draw = new DrawItemEventArgs(e.Graphics, e.Font, e.Bounds, e.Index, state);
- draw.DrawBackground();
-
- string text = Items[draw.Index].ToString();
- using (StringFormat format = new StringFormat())
- {
- format.LineAlignment = StringAlignment.Center;
- using (Brush brush = new SolidBrush(draw.ForeColor))
- {
- draw.Graphics.DrawString(text,
- draw.Font, brush,
- draw.Bounds,
- format);
- }
- }
+ // Select the item under the mouse and commit
+ SelectedIndex = IndexFromPoint(PointToClient(Cursor.Position));
+ CommitSelection();
}
protected override void DefWndProc(ref Message m)
@@ -117,12 +79,22 @@ namespace Acacia.Controls
Size prefSize = base.GetPreferredSize(proposedSize);
return new Size(prefSize.Width, ItemHeight * Math.Min(Items.Count, _owner.MaxDropDownItems));
}
+
+ public void CommitSelection()
+ {
+ _committedIndex = SelectedIndex;
+ base.OnSelectedIndexChanged(new EventArgs());
+ }
+
+ protected override void OnSelectedIndexChanged(EventArgs e)
+ {
+ // Don't notify until committed
+ }
}
#endregion
private readonly DropList _list;
- private int _ignoreListEvents;
#region Items properties
@@ -162,10 +134,14 @@ namespace Acacia.Controls
private void _list_SelectedIndexChanged(object sender, EventArgs e)
{
- if (_list.SelectedIndex >= 0 && _ignoreListEvents == 0)
+ if (_list.SelectedIndex >= 0)
{
Text = _list.SelectedItem.ToString();
}
+ else
+ {
+ Text = "";
+ }
}
public void BeginUpdate()
@@ -188,16 +164,8 @@ namespace Acacia.Controls
set
{
_list.BindingContext = new BindingContext();
- ++_ignoreListEvents;
- try
- {
- _list.DataSource = value;
- _list.SelectedIndex = -1;
- }
- finally
- {
- --_ignoreListEvents;
- }
+ _list.DataSource = value;
+ _list.SelectedIndex = -1;
}
}
@@ -219,7 +187,15 @@ namespace Acacia.Controls
case Keys.Down:
case Keys.Up:
User32.SendMessage(_list.Handle, (int)WM.KEYDOWN, new IntPtr((int)e.KeyCode), IntPtr.Zero);
- e.IsInputKey = false;
+ e.IsInputKey = true;
+ break;
+
+ // Enter commits the selected index and closes the drop down
+ case Keys.Enter:
+ case Keys.Tab:
+ _list.CommitSelection();
+ DroppedDown = false;
+ e.IsInputKey = e.KeyCode == Keys.Enter;
break;
default:
base.OnPreviewKeyDown(e);