【问题标题】:C# Ignoring Keydowns in ProcessKeyPreviewC# 忽略 ProcessKeyPreview 中的按键
【发布时间】:2014-07-07 16:05:35
【问题描述】:

你们都怎么了。我已经覆盖了 ProcessKeypreview 方法,这样我就可以检测到“WASD”键何时被持有,然后被释放。但是,当发生碰撞时,我会遇到问题,例如当按下“A”而“W”已经被按住时。在按住特定键时如何防止所有其他键按下?

这是我的代码的 sn-p:

const int WM_KEYDOWN = 0x0100;
const int WM_KEYUP = 0x0101;
protected override bool ProcessKeyPreview(ref Message m) 
{
    int msgVal = m.WParam.ToInt32();
    if (m.Msg == WM_KEYDOWN)
    {
        switch((Keys)msgVal) {
        case Keys.W:
            Console.WriteLine("W being held");
            break;

        case Keys.A:
            Console.WriteLine("A being held");
            break;
        }
    }

    if (m.Msg == WM_KEYUP) {
        switch((Keys)msgVal) {
            case Keys.W:
                Console.WriteLine("W released");
                break;

            case Keys.A:
                Console.WriteLine("A released");
                break;
        }
    }  
return base.ProcessKeyPreview(ref m);  
}

【问题讨论】:

  • 您的代码没有返回布尔值。至少,它应该返回return base.ProcessKeyPreview(ref m);。此外,你的常数是倒退的。 WM_KEYDOWN = 0x0100
  • 您的最终目标是知道某些键何时被按下正确?
  • 很好,我会编辑它。但与此同时,请随意假设该方法完美无缺。我的最终目标是防止字母 A 的 keydown 被触发,而字母 W 的 keydown 已经被触发。
  • 游戏不是这样运作的。最后一把钥匙获胜。试试看。

标签: c# events keydown


【解决方案1】:

保留一组(可能是HashSet<Keys>Keys 的当前被Adding 到 set on key-down 的键和Removeing 从 set on key-中按下的键-起来。

然后,由于您知道按下了多少键,如果您不想在特定键按下时不再处理任何键,您可以检查您设置的 Contains 是否为键。如果是,那么return true;

你的方法应该是这样的:

const int WM_KEYDOWN = 0x0101;
const int WM_KEYUP = 0x0100;
HashSet<Keys> keysDown = new HashSet<Keys>();
protected override bool ProcessKeyPreview(ref Message m) 
{
    int msgVal = m.WParam.ToInt32();
    if (m.Msg == WM_KEYDOWN)
    {
        keysDown.Add((Keys)msgVal);
        switch((Keys)msgVal) {
        case Keys.W:
            Console.WriteLine("W being held");
            break;

        case Keys.A:
            Console.WriteLine("A being held");
            break;
        }
        if (keysDown.Contains(keyToCheck))
            return true;
    }

    if (m.Msg == WM_KEYUP) {
        switch((Keys)msgVal) {
            case Keys.W:
                Console.WriteLine("W released");
                break;

            case Keys.A:
                Console.WriteLine("A released");
                break;
        }
        keysDown.Remove((Keys)msgVal);
    } 

    return base.ProcessKeyPreview(ref m);
}

由于您没有指定要检查的键 ("prevent all other keydowns while a specific key is being held down"),我只是将其保留为变量 keyToCheck。您可以更改条件以更改何时忽略按键。

或者,如果要检查的键是常量,那么您不需要Set,而可以只保留bool 来判断该键是否关闭:

const int WM_KEYDOWN = 0x0101;
const int WM_KEYUP = 0x0100;
bool keyToCheckDown = false;
protected override bool ProcessKeyPreview(ref Message m) 
{
    int msgVal = m.WParam.ToInt32();
    if (m.Msg == WM_KEYDOWN)
    {
        if ((Keys)msgVal == KEY_TO_CHECK)
            keyToCheckDown = true;
        switch((Keys)msgVal) {
        case Keys.W:
            Console.WriteLine("W being held");
            break;

        case Keys.A:
            Console.WriteLine("A being held");
            break;
        }
        // the second condition is necessary so that you don't "return true" the when the key to check is pressed.
        if (keyToCheckDown && (Keys)msgVal != KEY_TO_CHECK)
            return true;
    }

    if (m.Msg == WM_KEYUP) {
        switch((Keys)msgVal) {
            case Keys.W:
                Console.WriteLine("W released");
                break;

            case Keys.A:
                Console.WriteLine("A released");
                break;
        }
        if ((Keys)msgVal == KEY_TO_CHECK)
            keyToCheckDown = false;
    } 

    return base.ProcessKeyPreview(ref m);
}

这里的常量是KEY_TO_CHECK

我希望这会有所帮助!

【讨论】:

  • 壮观的解决方案,我的朋友!我相信这将非常有效。谢谢你的详尽。
猜你喜欢
  • 2013-11-21
  • 1970-01-01
  • 1970-01-01
  • 2013-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-04
  • 1970-01-01
相关资源
最近更新 更多