0

I have a UserControl that has inside some other controls and then a Panel that I use to paint custom shapes on mouse events. I would like to add some other functionalities but for that I would need to detect KeyDown and KeyUp while the mouse is drawing shapes on the Panel (in this situation UserControl.KeyDown/KeyUp never fire). How can be this achieved?

EDIT

Here is a minimum version for the UserControl where the problem can be seen:

public partial class UserControl1 : UserControl
{
    TextBox textBox1;
    Panel panel1;
    public UserControl1()
    {
        InitializeComponent();

        textBox1 = new System.Windows.Forms.TextBox();
        textBox1.Location = new System.Drawing.Point(0, 0);
        this.Controls.Add(this.textBox1);

        panel1 = new System.Windows.Forms.Panel();
        panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
        panel1.Location = new System.Drawing.Point(0, 25);
        panel1.Size = new System.Drawing.Size(300, 150);
        panel1.MouseEnter += new System.EventHandler(this.panel1_MouseEnter);
        this.Controls.Add(this.panel1);

        this.Size = new System.Drawing.Size(300, 200);
        this.KeyDown += UserControl1_KeyDown;
    }

    private void panel1_MouseEnter(object sender, EventArgs e)
    {
        panel1.Focus();
    }

    void UserControl1_KeyDown(object sender, KeyEventArgs e)
    {
        MessageBox.Show("Key down");
    }

}

When this control is inside a Form the "Key down" message is never displayed.

Mauro Ganswer
  • 1,379
  • 1
  • 19
  • 33
  • We'd need to see your code, otherwise we have no idea what the problem might be. Check out [ask] for some good guidelines. – Nate Barbettini Dec 13 '15 at 17:32
  • You may find the answers to [this question](http://stackoverflow.com/q/1152784/622391) useful. – Simon MᶜKenzie Dec 13 '15 at 21:59
  • 1
    Keyboard events are fired on the control that has the focus. That will never be the UserControl. You got this wrong because you can't *see* the focus, that's a strong UI usability problem. Check [this post](http://stackoverflow.com/a/3562449/17034). – Hans Passant Dec 13 '15 at 22:46
  • @Hans your hit was great and I modified your code for my needs. Now it works – Mauro Ganswer Dec 14 '15 at 10:21

1 Answers1

0

I took the code from Hans Passant here (great hint, many thanks!) and I modified it to suit my needs as follow:

class SelectablePanel : Panel
{
    public SelectablePanel()
    {
        this.SetStyle(ControlStyles.Selectable, true);
        this.TabStop = true;
    }
    protected override bool IsInputKey(Keys keyData)
    {
        if (keyData == Keys.Up || keyData == Keys.Down) return true;
        if (keyData == Keys.Left || keyData == Keys.Right) return true;
        return base.IsInputKey(keyData);
    }
    protected override void OnKeyDown(KeyEventArgs e)
    {
        var handler = KeyDown;
        if (handler != null) handler(this, e);
    }
    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        var handler = KeyPress;
        if (handler != null) handler(this, e);
    }
    protected override void OnKeyUp(KeyEventArgs e)
    {
        var handler = KeyUp;
        if (handler != null) handler(this, e);
    }
    protected override void OnMouseEnter(EventArgs e)
    {
        this.Focus();
        base.OnMouseEnter(e);
    }
    protected override void OnEnter(EventArgs e)
    {
        this.Invalidate();
        base.OnEnter(e);
    }
    protected override void OnLeave(EventArgs e)
    {
        this.Invalidate();
        base.OnLeave(e);
    }
    protected override void OnPaint(PaintEventArgs pe)
    {
        base.OnPaint(pe);
        if (this.Focused)
        {
            var rc = this.ClientRectangle;
            rc.Inflate(-2, -2);
            ControlPaint.DrawFocusRectangle(pe.Graphics, rc);
        }
    }

    [Browsable(true)]
    public new event EventHandler<KeyEventArgs> KeyDown;
    [Browsable(true)]
    public new event EventHandler<KeyEventArgs> KeyUp;
    [Browsable(true)]
    public new event EventHandler<KeyPressEventArgs> KeyPress;
}

Finally I modified my original code like this:

public partial class UserControl1 : UserControl
{
    TextBox textBox1;
    SelectablePanel selectablePanel;
    public UserControl1()
    {
        InitializeComponent();

        textBox1 = new System.Windows.Forms.TextBox();
        textBox1.Location = new System.Drawing.Point(0, 0);
        this.Controls.Add(this.textBox1);

        selectablePanel = new SelectablePanel();
        selectablePanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
        selectablePanel.Location = new System.Drawing.Point(0, 25);
        selectablePanel.Size = new System.Drawing.Size(300, 150);
        selectablePanel.KeyDown += panel1_KeyDown;
        this.Controls.Add(this.selectablePanel);

        this.Size = new System.Drawing.Size(300, 200);
    }

    void panel1_KeyDown(object sender, KeyEventArgs e)
    {
        MessageBox.Show("Key down");
    }
}

and now it works for what I need.

Community
  • 1
  • 1
Mauro Ganswer
  • 1,379
  • 1
  • 19
  • 33