unrelativity
unrelativity

Reputation: 3720

Is there any C# implementation or way to have a textbox that takes a key sequence as input?

I have an implementation which hooks into the keydown event, which suppresses the keypress event and does some magic. Now I want to show something more friendly than "ControlKey" etc, so there's a switch you can see in the code below. Except I've realised things like the number keys along the top end up as D1, D2, etc., and then there's things like Add showing up for the numpad +. In addition, Print Screen doesn't seem to be recognised.

Is there something I'm missing?

This is a hard question for me to describe fluently, but hopefully you get what I mean. If not I guess I'll be replying to comments and improving this as I go.

private int numKeys = 0;
private List<int> shortcutKeys = new List<int>();

private void textBoxRegionKeys_Click(object sender, EventArgs e)
{
    textBoxRegionKeys.SelectAll();
}

private void textBoxRegionKeys_KeyDown(object sender, KeyEventArgs e)
{
    // There are certain keys we want to ignore...
    if (e.KeyCode != Keys.Delete && e.KeyCode != Keys.Back)
    {
        // We can handle this ourselves, thanks
        e.SuppressKeyPress = true;

        // Shortern what we show
        string ret = e.KeyCode.ToString();
        switch (ret)
        {
            case "ControlKey": ret = "Ctrl"; break;
            case "ShiftKey": ret = "Shift"; break;
            case "Menu": ret = "Alt"; break;
        }

        // If we haven't selected anything, we should be appending
        if (textBoxRegionKeys.SelectionLength == 0)
        {
            if (numKeys > 0)
            {
                // Does our key already exist in the list?
                if (shortcutKeys.Exists(x => x == e.KeyValue))
                {
                    return;
                }

                textBoxRegionKeys.Text += " + ";
            }
            textBoxRegionKeys.Text += ret;
            shortcutKeys.Add(e.KeyValue);
            numKeys++;
        }
        else
        {
            textBoxRegionKeys.Text = ret;
            shortcutKeys.Clear();
            shortcutKeys.Add(e.KeyValue);
            numKeys = 1;
        }
    }
}

Upvotes: 0

Views: 330

Answers (1)

Chris Baxter
Chris Baxter

Reputation: 16353

The TextBox KeyDown/KeyPress etc will only be raised for keys that may be accepted as input in to the text box (and associated modifiers). As such, you will not see keys handled such as Print Screen etc. The best option I can think of is not ideal, but you could override the ProcessKeyPreview or some other Form level Message interceptor to get notified of ANY key press. Something like...

protected override bool ProcessKeyPreview(ref Message m)
{
  var keyCode = (Keys)Enum.ToObject(typeof (Keys), m.WParam);

  //Insert some logic 

  return base.ProcessKeyPreview(ref m);
}

Of course, this method will be invoked whenever the FORM has focus, and a key is pressed, so you would have to filter down by doing some form of check (which again is not ideal)

if(ReferenceEquals(ActiveControl, textBoxRegionKeys)) {}

Which if your dealing with things like UserControls will be very unreliable.

As for formatting in to nice friendly messages, I think you basically you will need your own map of special characters... I am not aware of any Globalized lookup for Keys. I will dig a little and update the answer if I find something.

Edit

Did a little digging and couldn't find anything obvious for nice key mappings. I would just create a map of "friendly" key names:

private static readonly Dictionary<Keys, String> KeysMap = new Dictionary<Keys, String>
                                                             {
                                                                { Keys.D1, "1"},
                                                                { Keys.D9, "9"}
                                                             };

And do something like:

  String friendlyKeyCode;
  if (!KeysMap.TryGetValue(keyCode, out friendlyKeyCode))
    friendlyKeyCode = keyCode.ToString();

Personally, I find this approach better than a massive switch... but that works too.

Upvotes: 1

Related Questions