65.9K
CodeProject 正在变化。 阅读更多。
Home

如何在 C# 中处理和使用同时按下两个或多个键的事件 - WASD 键盘游戏控制 -

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.43/5 (4投票s)

2016 年 10 月 23 日

公共领域

3分钟阅读

viewsIcon

18508

downloadIcon

162

处理多个按键事件的示例

引言

最近,我遇到了一个简单但对于我这个 C# 初学者来说无法解决的问题。
如何在像其他计算机游戏中一样使用 WASD 键盘按键?
 
解决此类问题涉及处理同时按下两个或多个键的键盘事件。
 
在我的程序中,我使用了两个标准的键盘 Key 事件处理程序。
OnKeyDownOnKeyUp 用于确定哪些键被按下和释放,
但程序运行不正确。
 
当我按下键 A 并且按住它时,我按下键 W,
程序运行完美,但是当我释放键 W 时
OnKeyDown 事件处理程序不识别键 A 仍然被按下。
 
在互联网上大量搜索有关此类问题的知识后,
我找到了这个答案:
 
引用
您依赖于键盘在按住某个键时重复该键。
一旦您按下另一个键,它就会停止工作。
您需要改用 Timer,并在 Tick 事件处理程序中
检查您想要移动的方向。现在,按键重复不再重要。
将 timer 的 Interval 属性设置为 15 或 31 以获得良好的一致性。
                                                       – Hans Passant
 
最后,这里有一个程序的例子,它可以很好地解决问题
可以在 Code Project 上公开分享作为 TIP & Trick(技巧与窍门)。

程序概述

该程序是在 C# 4.0 .Net 2.0 中作为 Windows 窗体应用程序开发的。
程序启动后,通过按键盘上的 WASD 键,
用户可以通过屏幕上显示的按键标志计数器值来观察,
程序检查并确认 WASD 键的按下状态的次数。

 

download下载开源代码 - 39.6 KB

 

技巧与窍门

由于标准的 OnKeyDownOnKeyUp 事件处理程序
只能在用户按下和释放一个键时进行注册,并且
不能同时按下和释放两个或多个键,
例外情况是 Alt、Shift 和 Control 键的组合,
在此程序中,带有每个观察键的按下标志变量的这些事件处理程序
用于确定和记忆按键按下/释放状态。
 
为了在按键按下/释放标志状态时引发动作,程序使用 System.Windows.Forms.Timer 类对象,该对象以用户定义的时间间隔引发事件。它在程序内部用作具有恒定时间的无限循环
以毫秒为单位设置的间隔,用于引发 Timer.Tick 事件处理程序,程序通过该处理程序调用用户 Main_Function(),其中定义了程序将在用户按下/释放键盘按键时采取的动作。
 

使用代码

与此技巧相关的程序代码专为学习而设计。
它有很好的注释,并且注释涵盖了问题解决的各个方面。
仔细彻底地阅读它。
 
为了实际使用,建议下载在 IDE Sharp Develop 中创建的完整解决方案。 在相同的 IDE 或 Visual Studio 中打开项目,构建并运行程序。
 

Download下载开源代码 - 39.6 KB

 
using System;
using System.Windows.Forms;

namespace WASD_keyboard_game_control
{
    public partial class MainForm : Form
    {

        //
        // Global variables declaration
        //

        //
        // Timer
        //
        // Implements a timer that
        // raises event at user defined interval
        //
        Timer Clock;

        //
        // Set Timer tick Interval in milliseconds
        //
        // By changing value of Interval,
        // we control how often the timer tick event handler is raised
        // and eventually the call frequency of Main_Function()
        //
        const int Interval = 15;

        //
        // Variables for counting the number
        // of times that program has confirmed
        // the key down state of WASD keys
        //
        int W = 0;
        int A = 0;
        int S = 0;
        int D = 0;

        //
        // Variables ( flags ) for memorizing
        // the key down state of WASD keys
        //
        // true  - key is down ( pressed )
        //
        // false - key is up ( released )
        //
        //
        bool w = false;
        bool a = false;
        bool s = false;
        bool d = false;

        //
        //
        //

        public MainForm()
        {
            //
            // The InitializeComponent() call is required
            // for Windows Forms designer support.
            //
            InitializeComponent();

            //
            // Call Initialize_Timer() function
            //
            Initialize_Timer();
        }
       

        void Initialize_Timer()
        {
            // Create new timer
            Clock = new Timer();

            // Set timer tick interval in milliseconds
            //
            // By changing value of interval,
            // we control how often the timer tick event handler is raised
            // and eventually the call frequency of Main_Function()
            //
            Clock.Interval = Interval;

            //
            // Add timer tick event handler
            //
            // This event handler is raised
            // every time timer make tick
            //
            // The smaller value for timer interval,
            // more often the event handler is raised
            //
            Clock.Tick += new System.EventHandler(this.ClockTick);

            //
            // Start timer
            //
            Clock.Start();
        }
       

        void ClockTick(object sender, EventArgs e)
        {
            //
            // Timer tick event handler
            //

            //
            // Call Main_Function()
            //
            Main_Function();

            //
            //
            //
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            //
            // This event handler is raised every time
            // some key on the keyboard is first pressed
            //

            base.OnKeyDown(e);

            //
            // Set corresponding key down flag state to true
            //

            if(e.KeyCode == Keys.W)
                w = true;
            if(e.KeyCode == Keys.A)
                a = true;
            if(e.KeyCode == Keys.S)
                s = true;
            if(e.KeyCode == Keys.D)
                d = true;
        }
       

        protected override void OnKeyUp(KeyEventArgs e)
        {
            //
            // This event handler is raised every time
            // some key on the keyboard is released
            //

            base.OnKeyUp(e);

            //
            // Set corresponding key down flag state to false
            //

            if(e.KeyCode == Keys.W)
                w = false;
            if(e.KeyCode == Keys.A)
                a = false;
            if(e.KeyCode == Keys.S)
                s = false;
            if(e.KeyCode == Keys.D)
                d = false;
        }
       

        void Main_Function()
        {
            //
            // Main function
            //

            //
            // This function is called every time the
            // timer tick event handler is raised
            //

            //
            // This function determines which key is pressed
            // upon key down flag value and updates corresponding counter value
            //
            // Counter value shows how many times program has confirmed the
            // key down state and not how many times user has pressed the key
            //
           

            //
            // Increase counter value if key is down
            //

            if(w)
                W++;
            if(a)
                A++;
            if(s)
                S++;          
            if(d)
                D++;

            //
            // Show values of counters
            //

            Label_W.Text = "W = " + W.ToString();
            Label_A.Text = "A = " + A.ToString();
            Label_S.Text = "S = " + S.ToString();
            Label_D.Text = "D = " + D.ToString();
        }
    }
}

关注点

学习如何处理同时按下两个或多个键盘按键的事件,并
通过使用 Timer 类对象在 Windows 窗体应用程序中模拟 WASD 游戏控制。
 
在学习了如何解决上述问题之后,
我了解到 System.Windows.Forms.Timer 类及其 Timer.Tick 事件
对于许多其他类似应用程序来说都很有趣且有用。

历史

最后更新 2016 年 10 月 22 日,作者

© . All rights reserved.