1
0
mirror of https://github.com/Kopano-dev/kopano-ol-extension.git synced 2023-10-10 13:37:40 +02:00

Fixed keyboard handling in combo box

This commit is contained in:
Patrick Simpson 2017-06-29 13:37:55 +02:00
parent fdf8350afb
commit acfc47f018

View File

@ -16,87 +16,49 @@ namespace Acacia.Controls
{
#region Drop-down list
/// <summary>
/// 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.
/// </summary>
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);