使用 KeyPressEvent 抑制键 "Bing"?

Suppress Key "Bing" with KeyPressEvent?

在我们的应用程序中,有一个用户控件,它允许输入一个数字(在 numericupdown 内),然后是 combobox,它允许 select SI 前缀( [p, n, µ, m, -, k, M, G, T] 从小到大)

现在,为了更容易使用,我认为在 numericUpDown 上捕获 KeyPress-Event 并相应地设置 combobox 会很好。 (如果按下m,select mili (m),如果按下G,select Giga (G)

这可以完美地与以下处理程序一起使用/select或:

 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;
            }
        }
    }

其中 TrySelect 只执行以下操作:

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;
    }

没关系,但每当用户在 numericupdown 上按下非数字键时都会听到 "BING"。

我读到了 e.SuppressKeyPress,不幸的是 KeyPressEventArgs 不可用 - 它仅适用于 KeyEventArgs

所以,用 KeyDown-Event 尝试整个事情是可行的。 (否 "BING")- 但我无法捕获大写键,因为每个 KeyDown 都会立即触发事件...

 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;
            }
        }
    }

有什么想法吗?

想出了一个办法:

使用KeyDown事件时,您可以使用e.Modifiers来检查是否同时按下了另一个键。

我不知道为什么,但是对于 KeyDown-事件 e.KeyValue 以及 e.KeyCode 总是 return 密钥的大写版本。

因此,我修改了处理程序以将每个字符转换为 lower-case,并且仅在同时按下 SHIFT 时才将其转换为 upper-Case:

有效 - 没有 "BING"(有效 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;
            }
        }
    }

上述解决方案不适用于µ(CTRL+ALT+m 或 ALT GR+m)


更新:这不是 100%,但我现在还没明白:

  • 如果 ALT-Key 被按下,Char-Code 总是报告 "M"。

更新 2:


所以,我不得不将 "m" 从与 char.isLetter() 匹配的对象中排除(如果 alt 被按下),最后添加另一个检查。

我发现,比较 e.KeyValue==77 按预期工作,而比较 c=='m' 没有...(然后 µ 被插入到 numericupdown,这它不应该)

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

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

不知道为什么 - 想法?

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;
            }

        }
    }