wpf 按住箭头键进行字符移动 C# .Net 问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19824260/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 10:01:20  来源:igfitidea点击:

Holding Arrow Keys Down For Character Movement C# .Net ISSUES

c#.netwpfanimationkeypress

提问by Ryan Brady

So in short i'm simply trying to move a rectangle around a Canvas object in a WPF application. What i have here is my KeyDown event function. The problem is, when i hold a key down for long, it launches this function over and over again rapidly and screws up my rectangle location code.

所以简而言之,我只是想在 WPF 应用程序中围绕 Canvas 对象移动一个矩形。我这里有的是我的 KeyDown 事件函数。问题是,当我长时间按住某个键时,它会一遍又一遍地快速启动此功能并搞砸我的矩形位置代码。

My theory/logic behind it: BECAUSE WHEN YOU HOLD A BUTTON DOWN ON A KEYBOARD IT DOES NOT MOVE SMOOTHLY (TEST IT ON THE SCROLL BAR IN YOUR BROWSER, IT STARTS, pauses, THEN CONTINUES SMOOTHLY), i want it to start a forms timer that moves the object in the UI. Then when the KeyUp event happens, the timer STOPS.

我背后的理论/逻辑:因为当你按住键盘上的按钮时,它不会平滑移动(在浏览器中的滚动条上测试它,它开始,暂停,然后继续平滑),我希望它启动一个表格在 UI 中移动对象的计时器。然后当 KeyUp 事件发生时,计时器停止。

public void Window_KeyDown(object sender, KeyEventArgs e)
{
    string msg;
    string keystr = e.Key.ToString();
    Key keyval = e.Key;


    switch (keystr)
    {
        case "Down":
            Console.WriteLine("Case 1");
            Display.Content = "Down";
            foreach (Character character in creatures)
            {
                //character.buttondown = true;
                character.Position("Down");
            }
            break;
        case "Up":
            Console.WriteLine("Case 2");
            Display.Content = "Up";
            foreach (Character character in creatures)
            {
                //character.buttondown = true;
                character.Position("Up");
            }
            break;
        case "Left":
            Console.WriteLine("Case 3");
            Display.Content = "Left";
            foreach (Character character in creatures)
            {
                //character.buttondown = true;
                character.Position("Left");
            }
            break;
        case "Right":
            Display.Content = "Right";
            foreach (Character character in creatures)
            {

                //character.buttondown = true;
                character.Position("Right");
            }
            break;
    }
}

public void Window_KeyUp(object sender, KeyEventArgs e)
{
    Display.Content = "No key is pressed.";
    foreach (Character character in creatures)
    {
        if (e.Key == Key.Right)
        {
            character.StopIt();
        }
        if (e.Key == Key.Left)
        {
            character.StopIt();
        }
        if (e.Key == Key.Up)
        {
            character.StopIt();
        }
        if (e.Key == Key.Down)
        {
            character.StopIt();
        }

    }
}

and just for reference if you need my rectangleclass code i'll post what happens if the RIGHT arrow key is pressed:

如果您需要我的矩形类代码,仅供参考,我将发布如果按下向右箭头键会发生什么:

  1. Position is called

    public void Position(String Direction)
    {
    
        if (Direction == "Right")
        {
            tmr = new System.Windows.Forms.Timer();
            tmr.Interval = this.waitTime;
            tmr.Tick += new EventHandler(GoRight);
            tmr.Start();
        }
     }
    
  2. GoRight is called:

    public void GoRight(object sender, System.EventArgs e)
    {
        if (x < Background.ActualWidth - CharacterWidth)
        {
            if (goRight)
            {
                x += incrementSize;
                CharacterImage.SetValue(Canvas.LeftProperty, x);
    
            }
            if (x > Background.ActualWidth - CharacterWidth)
            {
                goRight = false;
                tmr.Stop();
            }
        }
    
    }
    
  1. 位置被称为

    public void Position(String Direction)
    {
    
        if (Direction == "Right")
        {
            tmr = new System.Windows.Forms.Timer();
            tmr.Interval = this.waitTime;
            tmr.Tick += new EventHandler(GoRight);
            tmr.Start();
        }
     }
    
  2. GoRight 被称为:

    public void GoRight(object sender, System.EventArgs e)
    {
        if (x < Background.ActualWidth - CharacterWidth)
        {
            if (goRight)
            {
                x += incrementSize;
                CharacterImage.SetValue(Canvas.LeftProperty, x);
    
            }
            if (x > Background.ActualWidth - CharacterWidth)
            {
                goRight = false;
                tmr.Stop();
            }
        }
    
    }
    

Finally, StopIt is called in the KeyUp event:

最后,在 KeyUp 事件中调用 StopIt:

public void StopIt()
{
    tmr.Stop();
    goRight = true;
    goLeft = true;
    goUp = true;
    goDown = true;
}

I've only been learning c# for a couple months now so i'm trying to keep it relatively simple if possible, and only use .net.

我现在只学习了几个月的 c#,所以如果可能的话,我试图让它保持相对简单,并且只使用 .net。

Any help would be appreciated!!

任何帮助,将不胜感激!!

EDIT:: MY SOLUTION:

编辑::我的解决方案:

I simply made a while(flag) loop around my switch case. Then i set flag = false within the cases. When Key UP is pressed i set flag equal to true again. YAY

我只是在我的开关盒周围做了一个 while(flag) 循环。然后我在案例中设置 flag = false。当按下键 UP 时,我再次将标志设置为 true。好极了

采纳答案by Ben T

I assume that you want your character to move on the initial KeyDown event. Then you want to ignore any subsequent KeyDown events until you get a KeyUp event.

我假设您希望您的角色在初始 KeyDown 事件上移动。然后您想忽略任何后续的 KeyDown 事件,直到您获得 KeyUp 事件。

So you can ignore the subsequent KeyDown events by checking e.IsRepeat e.g.

所以你可以通过检查 e.IsRepeat 例如忽略后续的 KeyDown 事件

public void Window_KeyDown(object sender, KeyEventArgs e)
{
    if (e.IsRepeat) return;

    // rest of your code...

BTW, the non-smooth movement that you observe when scrolling an application is caused by the keyboard repeat delay. You can set this in the keyboard properties or though http://msdn.microsoft.com/en-us/library/system.windows.systemparameters.keyboarddelay.aspx

顺便说一句,您在滚动应用程序时观察到的非平滑移动是由键盘重复延迟引起的。您可以在键盘属性中或通过http://msdn.microsoft.com/en-us/library/system.windows.systemparameters.keyboarddelay.aspx 进行设置

回答by Dropn Fbombs

I don't know enough about WPF to tell you what is going on, though you may be correct about the push button/pause thing. It depends on how WPF treats keypresses. My guess would be that it does so the same way most Microsoft forms work; it has a pause to keep you from typing multiple characters at a time. There may be a way around this but I'm not sure.

我对 WPF 的了解还不够多,无法告诉您发生了什么,尽管您对按钮/暂停的事情可能是正确的。这取决于 WPF 如何处理按键。我的猜测是它的工作方式与大多数 Microsoft 表单的工作方式相同;它有一个暂停,以防止您一次输入多个字符。可能有办法解决这个问题,但我不确定。

What I will say though is that you should use something designed for games. When I first tried creating games I did so in a style similar to what you are doing and it doesn't work. What you are using is designed for office software and will not give you access to what you need; at least not without fighting and workarounds. As was suggested by Alex Beisley look into XNA. It's a dead language unfortunately but it died fairly recently. It uses c#, was made by Microsoft, and is powerful enough to do what you want without fighting you and easy enough to use once you get the hang of it. It's a shame to see it killed off.

不过我要说的是,您应该使用专为游戏设计的东西。当我第一次尝试创建游戏时,我的风格与您正在做的类似,但它不起作用。您使用的是专为办公软件设计的,不会让您访问所需的内容;至少不是没有战斗和变通方法。正如亚历克斯·贝斯利 (Alex Beisley) 所建议的那样,研究 XNA。不幸的是,它是一种死语言,但它最近死了。它使用由 Microsoft 制造的 c#,功能强大,可以做您想做的事,而无需与您争吵,而且一旦掌握了它,就很容易使用。看到它被杀死真是太可惜了。

If you want to torture yourself then I'd suggest going the route I've been trying which is to learn C++ and DirectX. It is not easy and you will need to be patient and go through multiple tutorials (no one tutorial seems to do a good job explaining anything). DirectX and C++ are not going anywhere soon, so they are a safe bet if you are looking to get into a long term language.

如果你想折磨自己,那么我建议走我一直在尝试的路线,即学习 C++ 和 DirectX。这并不容易,您需要耐心并阅读多个教程(似乎没有一个教程能很好地解释任何内容)。DirectX 和 C++ 不会很快消失,所以如果你想进入一种长期语言,它们是一个安全的赌注。