Search code examples
c#winformskeypresskeydown

Suppress Key "Bing" with KeyPressEvent?


Within our application, there is a usercontrol, which allows to enter a number (inside a numericupdown) followed by a combobox which allows to select the SI-Prefix ([p, n, µ, m, -, k, M, G, T] small to big)

Now, for easier usage, I thought it would be nice to capture the KeyPress-Event on the numericUpDown and set the combobox accordingly. (If m is pressed, select mili (m), if G is pressed, select Giga (G))

This works flawless with the following handler / selector:

 private void numericUpDown1_KeyPress(object sender, KeyPressEventArgs e)
    {
        if (char.IsLetter(e.KeyChar))
        {
            //Check, if its valid for si prefixes. 
            if (this.siSelector1.TrySelect(e.KeyChar)
            {
                e.Handled = true;
            }
        }
    }

Where TrySelect does nothing but the following:

public Boolean TrySelect(Char chr)
    {
        var entry = this.comboBox_siPrefix.Items.Cast<KeyValuePair<String,Double>>().Where(e => e.Key.Contains("(" + chr + ")")).FirstOrDefault();

        if (!entry.Equals(new KeyValuePair<String, Double>()))
        {
            this.comboBox_siPrefix.SelectedItem = entry;
            return true;
        }
        return false;
    }

That's fine, but everytime the user hears a "BING" whenever a non-numeric Key is pressed on the numericupdown.

I read about e.SuppressKeyPress, which unfortunately isn't available with KeyPressEventArgs - it's only available for KeyEventArgs.

So, trying the whole thing with the KeyDown-Event works. (No "BING") - but I wasn't able to capture capital keys, as every KeyDown will fire the Event immediately...

 private void numericUpDown1_KeyDown(object sender, KeyEventArgs e)
    {
        KeysConverter kc = new KeysConverter();
        if (char.IsLetter(kc.ConvertToString(e.KeyCode)[0]))
        {
            //Check, if its valid for si prefixes. 
            if (this.siSelector1.TrySelect(kc.ConvertToString(e.KeyCode)[0]))
            {
                e.Handled = true;
                e.SuppressKeyPress = true;
            }
        }
    }

Any Ideas?


Solution

  • Figured out a way:

    When Using KeyDown-Event, you can use e.Modifiers to check, if another key is down'd at the same time.

    I dunno why, but for the KeyDown-Event e.KeyValue as well as e.KeyCode always return the CAPITAL version of the key.

    So, I modified the handler to convert every char to lower-case, and only convert it to upper-Case if SHIFT is pressed at the same time:

    Works - no "BING" (for valid SI-Prefixes). :-)

    private void numericUpDown1_KeyDown(object sender, KeyEventArgs e)
        {
            KeysConverter kc = new KeysConverter();
            char c = char.ToLower(kc.ConvertToString(e.KeyValue)[0]); 
            if (char.IsLetter(c))
            {
                //Caps? 
                if (e.Modifiers == Keys.Shift)
                {
                    c = char.ToUpper(c);
                }
    
                //Check, if its valid for si prefixes.
                if (this.siSelector1.TrySelect(c))
                {
                    e.Handled = true;
                    e.SuppressKeyPress = true;
                }
            }
        }
    

    The above solution does not apply for µ (CTRL+ALT+m or ALT GR+m)


    Update: This is not 100%, but I didn't get it by now:

    • IF the ALT-Key is pressed, The Char-Code always reports a "M".

    Update 2:


    So, I had to exclude the "m" from beeing matched with char.isLetter() (if alt is pressed) and finally add another check.

    I found, that comparing e.KeyValue==77 worked as expected, while comparing c=='m' didn't... (then µ was inserted into the numericupdown, which it shouldn't)

    if (ctrl && alt && c=='m'):

    enter image description here

    if (ctrl && alt && e.KeyValue==77)

    enter image description here

    Dunno why - Ideas?

    private void numericUpDown1_KeyDown(object sender, KeyEventArgs e)
        {
            KeysConverter kc = new KeysConverter();
            char c = char.ToLower(kc.ConvertToString(e.KeyValue)[0]);
    
            Boolean ctrl = e.Control;
            Boolean alt = e.Alt;
            Boolean shift = e.Shift;
            int keyPadStart = (int)Keys.NumPad0;
            int keyPadEnd = (int)Keys.NumPad9;
    
            if (e.KeyValue >= keyPadStart && e.KeyValue <= keyPadEnd)
            {
                //send to numeric updown. 
                return;
            }
    
            if (char.IsLetter(c) && !alt)
            {
                if (shift) c = char.ToUpper(c);
    
                //Check, if its valid for si prefixes.
                if (this.siSelector1.TrySelect(c))
                {
                    e.Handled = true;
                    e.SuppressKeyPress = true;
                }
            }
    
            //not working: if (ctrl && alt && c=='m')
            if (ctrl && alt && e.KeyValue==77)
            {
                //Check, if its valid for si prefixes.
                if (this.siSelector1.TrySelect('µ'))
                {
                    e.Handled = true;
                    e.SuppressKeyPress = true;
                }
    
            }
        }