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=mscorlibStackTrace:at System.Convert.ToChar(Int32 value)... "

これが問題の原因となっている行だと思います。

char.IsControl(Convert.ToChar(keyData))

...しかし、Shiftに問題があるのはなぜですか。また、Shiftキーを無視するようにするにはどうすればよいですか(ユーザーがDGVでShiftキーを押す理由はありません)。

アップデート

私はケツァルコアトルの答えを完全には理解していないことを認めなければなりませんが、私はそれをこのように適用しようとしました:

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

上記の2番目のアプローチを使用し、「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間違った方法でCharに変換しているためです。Convert.ToCharはそれを処理しません。

Keys列挙には、shift、alt、controlなどのすべての修飾子をフィルターで除外するために使用する必要がある「マスク」が含まれています。

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

これで、keycodeはキーで定義された通常のA / B / C / ...値の1つと正確に等しくなり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キーの列挙を見るとShift、65536の値があり、これは範囲外です。char

于 2012-09-28T22:01:15.973 に答える
1

Keysをに変換しないでくださいchar。これは動作しません。それが数字であるかどうかをテストします

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 に答える