0

我在派生自 DataGridView 的自定义类中有此代码:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    if (char.IsNumber(Convert.ToChar(keyData)) || 
        char.IsControl(Convert.ToChar(keyData)) || 
        (keyData >= Keys.NumPad0 && keyData <= Keys.NumPad9) ||
        (keyData == Keys.Up) ||
        (keyData == Keys.Down) ||
        (keyData == Keys.Left) ||
        (keyData == Keys.Right) ||
        (keyData == Keys.Home) ||
        (keyData == Keys.PageDown) ||
        (keyData == Keys.PageUp) ||
        (keyData == Keys.Space) ||
        (keyData == Keys.Back) ||
        (keyData == Keys.Decimal))
    {
        return false;
    }
    return true;
}

我可以输入数据(数字和.),并从一个单元格到另一个单元格,但是如果我按“Shift”键,我会得到,“System.OverflowException 未被用户代码处理 Message=Value 太大或太小一个字符。Source=mscorlib StackTrace: at System.Convert.ToChar(Int32 value)..."

我认为这是导致问题的行:

char.IsControl(Convert.ToChar(keyData))

...但是为什么 Shift 有问题,我应该怎么做才能让它忽略 Shift 键(用户没有理由按下 DGV 中的 Shift 键)。

更新

我必须承认我不太理解 quetzalcoatl 的回答,但我试图以这种方式应用它:

Keys specials = keyData & Keys.Modifiers; 
Keys keycode = keyData & ~Keys.Modifiers;

if (char.IsNumber(Convert.ToChar(keyData)) || 
    //char.IsControl(Convert.ToChar(keyData)) || 
    //(keyData == specials) || <-- didn't work
    //(keyData == keycode) ||  <-- didn't work
    (keyData != specials) ||
    (keyData != keycode) ||
    . . .

...并且仍然得到同样的错误。我如何应用他提供的信息来解决问题?

更新 2

我仍在为此苦苦挣扎。

我试过这个:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    Keys keycode = keyData & ~Keys.Modifiers;

    if (keycode >= Keys.D0 && keycode <= Keys.D9 ||          
        keycode >= Keys.NumPad0 && keycode <= Keys.NumPad9 ||
        (keycode == Keys.Up) ||
        (keycode == Keys.Down) ||
        (keycode == Keys.Left) ||
        (keycode == Keys.Right) ||
    (keyData == Keys.Tab) ||
        (keycode == Keys.Tab) ||
        (keycode == Keys.Home) ||
        (keycode == Keys.PageDown) ||
        (keycode == Keys.PageUp) ||
        (keycode == Keys.Space) ||
        (keycode == Keys.Back) ||
        (keycode == Keys.Decimal))
    {
        return false;
    }
    return true;
}

...和这种方法:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        Keys keycode = keyData & ~Keys.Modifiers;

        bool isDigit = keycode >= Keys.D0 && keycode <= Keys.D9 ||
                       keycode >= Keys.NumPad0 && keycode <= Keys.NumPad9;
        bool isControl = (keyData & Keys.Modifiers) != Keys.None;

        if (isDigit ||
            isControl ||
            (keyData == Keys.Up) ||
            (keyData == Keys.Down) ||
            (keyData == Keys.Left) ||
            (keyData == Keys.Right) ||
        (keyData == Keys.Tab) ||
            (keyData == Keys.Home) ||
            (keyData == Keys.PageDown) ||
            (keyData == Keys.PageUp) ||
            (keyData == Keys.Space) ||
            (keyData == Keys.Back) ||
            (keyData == Keys.Decimal))
        {
            return false;
        }
        return true;
}

它们都解决了导致溢出的 Shift 键,但它们都防止输入小数。我不明白这一点,因为 Decimal 被(据说)明确允许。其他所有明确检查的内容都是允许的(Home、PageUp、PageDown 等)——它只是“。” 被禁止进入的角色。

更新 3

使用上面的第二种方法并将“Keys.Decimal”替换为“Keys.OemPeriod”可以:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    Keys keycode = keyData & ~Keys.Modifiers;

    bool isDigit = keycode >= Keys.D0 && keycode <= Keys.D9 ||
                   keycode >= Keys.NumPad0 && keycode <= Keys.NumPad9;
    bool isControl = (keyData & Keys.Modifiers) != Keys.None;

    if (isDigit ||
        isControl ||
        (keyData == Keys.Up) ||
        (keyData == Keys.Down) ||
        (keyData == Keys.Left) ||
        (keyData == Keys.Right) ||
        (keyData == Keys.Home) ||
        (keyData == Keys.Tab) ||
        (keyData == Keys.PageDown) ||
        (keyData == Keys.PageUp) ||
        (keyData == Keys.Space) ||
        (keyData == Keys.Back) ||
        (keyData == Keys.OemPeriod))
    {
        return false;
    }
    return true;
}
4

3 回答 3

3

这是因为您Keys keyData以错误的方式将 in 转换为 Char 。Convert.ToChar 不处理。

Keys 枚举包含 `` 掩码,用于过滤掉所有修饰符,如 shift、alt、control:

Keys specials = keyData & Keys.Modifiers;
Keys keycode = keyData & ~Keys.Modifiers;

现在,keycode恰好等于 Keys 中定义的正常 A/B/C/... 值之一,并且specials是由 Control/Alt/Shift 修饰符组成的位集。

错误的确切原因是,虽然一些“低键值”(a、b、c、..z、0-9 等)实际上与 ASCII 码相等/相似,但“修饰符”是提供一个非常高的整数,按位或运算到基本键码:

Keys justA = Keys.A;
Keys theAandShift = Keys.A | Keys.Shift;

等等。这导致“A with Shift”在 ASCII 甚至 Unicode 的意义上具有完全荒谬的数值......这就是为什么你必须首先切断修饰符代码!

编辑:

Keys specials = keyData & Keys.Modifiers;
Keys keycode = keyData & ~Keys.Modifiers;

bool withShift = specials.HasFlag( Keys.Shift );
bool withControl = specials.HasFlag( Keys.Control );
bool withAlt = specials.HasFlag( Keys.Alt );

if(keycode == Keys.F1 && !withShift && !withControl && !withAlt)
    ; // it was plain F1 with no specials

else if(keycode == Keys.VolumeUp)
    ; // it was 'volume-up' key with any or none of the modifiers

else if(keycode >= Keys.A && keycode <= Keys.Z && withControl)
    ; // it was CTRL+Letter

else if(keycode >= Keys.D0 && keycode <= Keys.D9 && withShift)
    ; // it was SHIFT+Digit

等等

于 2012-09-28T22:03:11.737 回答
2

Keys不能转换成char这样的。如果您查看KeysShift枚举,它的值为 65536,超出了char

于 2012-09-28T22:01:15.973 回答
1

不要将 a 转换Keyschar. 这不起作用。测试它是否是一个数字

Keys code = keyData & ~Keys.Modifiers;

bool isDigit = code >= Keys.D0 && code <= Keys.D9 ||
               code >= Keys.NumPad0 && code <= Keys.NumPad9

测试它是否是一个控制键

bool isControl = (keyData & Keys.Modifiers) != Keys.None;
于 2012-09-28T23:40:21.517 回答