From 2490952c0bc2d9ef2497b0306f45431f8a349320 Mon Sep 17 00:00:00 2001
From: Patrick Simpson
Date: Wed, 28 Jun 2017 11:58:25 +0200
Subject: [PATCH] Simplified event handling for combo box, without message
filter
---
.../Controls/KAbstractComboBox.cs | 164 ++++++++----------
.../AcaciaZPushPlugin/Controls/KComboBox.cs | 15 +-
.../AcaciaZPushPlugin/Controls/KListBox.cs | 14 +-
3 files changed, 95 insertions(+), 98 deletions(-)
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KAbstractComboBox.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KAbstractComboBox.cs
index 71df804..deb9380 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KAbstractComboBox.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KAbstractComboBox.cs
@@ -12,7 +12,7 @@ using System.Windows.Forms;
namespace Acacia.Controls
{
- public abstract class KAbstractComboBox : ContainerControl, IMessageFilter
+ public abstract class KAbstractComboBox : ContainerControl
{
#region Properties
@@ -63,11 +63,7 @@ namespace Acacia.Controls
_state.AddControl(_edit);
_edit.TextChanged += _edit_TextChanged;
_edit.LostFocus += _edit_LostFocus;
- }
-
- private void _edit_LostFocus(object sender, EventArgs e)
- {
- DroppedDown = false;
+ _edit.PreviewKeyDown += _edit_PreviewKeyDown;
}
@@ -75,15 +71,15 @@ namespace Acacia.Controls
#region Text edit
- private void _edit_TextChanged(object sender, EventArgs e)
- {
- OnTextChanged(new EventArgs());
- }
-
override public string Text
{
get { return _edit.Text; }
- set { _edit.Text = value; }
+ set
+ {
+ _edit.Text = value;
+ // Set the cursor after the text
+ _edit.Select(_edit.Text.Length, 0);
+ }
}
public void FocusEdit()
@@ -91,6 +87,63 @@ namespace Acacia.Controls
_edit.Select();
}
+ private void _edit_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
+ {
+ switch (e.KeyCode)
+ {
+ case Keys.Escape:
+ // Escape closes the dropdown
+ if (DroppedDown)
+ {
+ DroppedDown = false;
+ e.IsInputKey = false;
+ return;
+ }
+ break;
+ case Keys.Down:
+ // Down opens the drop down
+ if (!DroppedDown)
+ {
+ DroppedDown = true;
+ e.IsInputKey = false;
+ return;
+ }
+ break;
+ }
+ OnPreviewKeyDown(e);
+ }
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
+ internal static extern IntPtr GetFocus();
+
+ private Control GetFocusedControl()
+ {
+ Control focusedControl = null;
+ // To get hold of the focused control:
+ IntPtr focusedHandle = GetFocus();
+ if (focusedHandle != IntPtr.Zero)
+ // Note that if the focused Control is not a .Net control, then this will return null.
+ focusedControl = Control.FromHandle(focusedHandle);
+ return focusedControl;
+ }
+
+ private void _edit_LostFocus(object sender, EventArgs e)
+ {
+ System.Diagnostics.Trace.WriteLine("_edit_LostFocus: " + GetFocusedControl()?.Name);
+ DroppedDown = false;
+ }
+
+ protected override void OnGotFocus(EventArgs e)
+ {
+ base.OnGotFocus(e);
+ System.Diagnostics.Trace.WriteLine("OnGotFocus");
+ }
+
+ private void _edit_TextChanged(object sender, EventArgs e)
+ {
+ OnTextChanged(new EventArgs());
+ }
+
#endregion
#region Drop down
@@ -118,6 +171,7 @@ namespace Acacia.Controls
_dropListHost.Padding = new Padding(0);
_dropListHost.Margin = new Padding(0);
_dropListHost.AutoSize = false;
+ _dropListHost.GotFocus += (s, e) => System.Diagnostics.Trace.WriteLine("_dropListHost.GotFocus");
_dropDown = new ToolStripDropDown();
_dropDown.Padding = new Padding(0);
@@ -127,89 +181,7 @@ namespace Acacia.Controls
_dropDown.Items.Add(_dropListHost);
_dropDown.Closed += _dropDown_Closed;
_dropDown.AutoClose = false;
-
- Application.AddMessageFilter(this);
- }
-
- protected override void OnHandleDestroyed(EventArgs e)
- {
- Application.RemoveMessageFilter(this);
- base.OnHandleDestroyed(e);
- }
-
- public bool PreFilterMessage(ref Message m)
- {
- switch ((WM)m.Msg)
- {
- case WM.KEYDOWN:
- switch((VirtualKeys)m.WParam.ToInt32())
- {
- case VirtualKeys.Escape:
- // Escape closes the popup
- if (DroppedDown)
- {
- DroppedDown = false;
- return true;
- }
- break;
- case VirtualKeys.Down:
- // Down opens the drop down
- if (!DroppedDown)
- {
- DroppedDown = true;
- return true;
- }
- break;
- }
- ForwardKeyMessage(m);
- break;
- case WM.CHAR:
- case WM.KEYUP:
- ForwardKeyMessage(m);
- break;
- case WM.LBUTTONDOWN:
- case WM.RBUTTONDOWN:
- case WM.MBUTTONDOWN:
- case WM.NCLBUTTONDOWN:
- case WM.NCRBUTTONDOWN:
- case WM.NCMBUTTONDOWN:
- if (_dropDown.Visible)
- {
- //
- // When a mouse button is pressed, we should determine if it is within the client coordinates
- // of the active dropdown. If not, we should dismiss it.
- //
- int i = unchecked((int)(long)m.LParam);
- short x = (short)(i & 0xFFFF);
- short y = (short)((i >> 16) & 0xffff);
- Point pt = new Point(x, y);
-
- // Map to global coordinates
- User32.MapWindowPoints(m.HWnd, IntPtr.Zero, ref pt, 1);
- System.Diagnostics.Trace.WriteLine(string.Format("MOUSE: {0} - {1}", pt, _dropDown.Bounds));
- if (!_dropDown.Bounds.Contains(pt))
- {
- // the user has clicked outside the dropdown
- User32.MapWindowPoints(m.HWnd, Handle, ref pt, 1);
- if (!ClientRectangle.Contains(pt))
- {
- // the user has clicked outside the combo
- DroppedDown = false;
- }
- }
- }
- break;
- }
- return false;
- }
-
- private void ForwardKeyMessage(Message m)
- {
- System.Diagnostics.Trace.WriteLine("KEY: " + m);
- if ((WM)m.Msg == WM.KEYDOWN)
- {
- OnPreviewKeyDown(new PreviewKeyDownEventArgs((Keys)m.WParam.ToInt32()));
- }
+ _dropDown.GotFocus += (s, e) => System.Diagnostics.Trace.WriteLine("_dropDown.GotFocus");
}
// Cannot use visibility of _dropDown to keep the open state, as clicking on the button already
@@ -249,10 +221,12 @@ namespace Acacia.Controls
_dropControl.Height = Util.Bound(prefSize.Height, minHeight, maxHeight);
// Show the drop down below the current control
_dropDown.Show(this.PointToScreen(new Point(0, Height)));
+ _dropControl.Capture = true;
}
else
{
_dropDown.Close();
+ _dropControl.Capture = false;
}
_isDroppedDown = value;
}
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KComboBox.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KComboBox.cs
index ac0b30d..bc950ca 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KComboBox.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KComboBox.cs
@@ -47,14 +47,25 @@ namespace Acacia.Controls
MaxDropDownItems = 8;
_list = new KListBox();
_list.IntegralHeight = true;
+ _list.TabStop = false;
DropControl = _list;
_list.DisplayMember = "DisplayName"; // TODO: remove from here
_list.SelectedIndexChanged += _list_SelectedIndexChanged;
+ _list.GotFocus += _list_GotFocus;
+ }
+
+ private void _list_GotFocus(object sender, EventArgs e)
+ {
+ System.Diagnostics.Trace.WriteLine("_list_GotFocus");
+
}
private void _list_SelectedIndexChanged(object sender, EventArgs e)
{
- System.Diagnostics.Trace.WriteLine("SELECTED: " + _list.SelectedIndex);
+ if (_list.SelectedIndex >= 0)
+ {
+ Text = _list.SelectedItem.ToString();
+ }
}
public void BeginUpdate()
@@ -95,9 +106,11 @@ namespace Acacia.Controls
{
switch(e.KeyCode)
{
+ // Forward cursor keys to the list
case Keys.Down:
case Keys.Up:
User32.SendMessage(_list.Handle, (int)WM.KEYDOWN, new IntPtr((int)e.KeyCode), IntPtr.Zero);
+ e.IsInputKey = false;
break;
default:
base.OnPreviewKeyDown(e);
diff --git a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KListBox.cs b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KListBox.cs
index b22b389..9738892 100644
--- a/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KListBox.cs
+++ b/src/AcaciaZPushPlugin/AcaciaZPushPlugin/Controls/KListBox.cs
@@ -16,18 +16,20 @@ namespace Acacia.Controls
{
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
DrawMode = DrawMode.OwnerDrawFixed;
+ SetStyle(ControlStyles.Selectable, true);
}
protected override void OnMouseMove(MouseEventArgs e)
{
- Point point = PointToClient(Cursor.Position);
- int newIndex = IndexFromPoint(point);
+ int newIndex = IndexFromPoint(PointToClient(Cursor.Position));
if (newIndex != _hoverIndex)
{
int oldIndex = _hoverIndex;
_hoverIndex = newIndex;
InvalidateItem(oldIndex);
InvalidateItem(_hoverIndex);
+ if (SelectedIndex != oldIndex && SelectedIndex != _hoverIndex)
+ InvalidateItem(SelectedIndex);
}
}
@@ -37,6 +39,14 @@ namespace Acacia.Controls
_hoverIndex = -1;
}
+ protected override void OnMouseDown(MouseEventArgs e)
+ {
+ base.OnMouseDown(e);
+ // Perform the select here.
+ // TODO: this really is for ComboBox, where the list hides before the event is handled
+ SelectedIndex = IndexFromPoint(PointToClient(Cursor.Position));
+ }
+
protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);