在除 Form 之外的 class 上接收和读取 KeyEventArgs 事件

Receiving and reading out KeyEventArgs event on a class other than a Form

我目前正在开发一个小游戏作为 WinForms 项目。游戏场由玩家(一个单独的 class)可以继续前进的瓷砖网格构建而成。我想让玩家用箭头键移动并为它设置了一个事件处理程序,但它似乎从未被调用过。

(最小化)播放器 class,实现了 KeyEventArgs 的 System.Windows.Forms 包:

public class Player : MovableObject
{
    public Player(Playtile position) : base(position)
    {
        EntityColor = ElementColors.PlayerColor;
        PostConstructor(position);
    }

    /// <summary>
    /// Reads keypress via eventhandler KeyEventArgs (key down). 
    /// </summary>
    private void ReadKeyDown(object sender, KeyEventArgs e)
    {
        switch (e.KeyCode)
        {
            case Keys.Up:
                // move up.
                break;
            case Keys.Right:
                // move right.
                break;
            case Keys.Down:
                // move down.
                break;
            case Keys.Left:
                // move left.
                break;
        }
    }
}

目前,ReadKeyDown 从未被调用。我如何实际将 KeyEventDown 事件分配/绑定到播放器,以便它实际上在按键按下时调用该方法?

KeyEventArgs in C# 似乎只是说 this.KeyDown += ReadKeyDown;,但它不会将 KeyDown 识别为任何东西,也不会给我可能缺少的程序集引用。

KeyDownControl 的成员,因此在您的情况下,您可以在 Form.

中订阅该活动

喜欢以下内容:

public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();
        textBox1.KeyDown += TextBox1_KeyDown;
    }

    private void TextBox1_KeyDown(object sender, KeyEventArgs e)
    {
    }
}

完整示例见官方文档:

https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.control.keydown?view=netframework-4.7.2

现在您可以做的是在收到此类事件后在目标 class 中调用一个方法:

public class MyClass
{
    public void OnKeyDown(KeyEventArgs e)
    {
        // ...
    }
}

public partial class Form2 : Form
{
    MyClass _instance = new MyClass();

    public Form2()
    {
        InitializeComponent();
        textBox1.KeyDown += TextBox1_KeyDown;
    }

    private void TextBox1_KeyDown(object sender, KeyEventArgs e)
    {
        _instance.OnKeyDown(e);
    }
}

您可以直接在 class 中订阅 KeyDown 活动:

public Player(Playtile position, Form form) : base(position) // <--- form parameter
{
    EntityColor = ElementColors.PlayerColor;
    PostConstructor(position);
    form.KeyDown += ReadKeyDown; // <--- subscribing to the event
}

但是有一个问题。现在表单持有对 Player 对象的引用,并且在关闭表单之前不会对对象进行垃圾回收。如果 Player 的生命周期与 form 的生命周期相同,这不是问题。但是,如果您创建了许多短命的玩家,那么当您不再需要它们时,您应该取消订阅表单的事件,方法是向玩家添加如下方法:

public void Dispose(Form form)
{
    form.KeyDown -= ReadKeyDown;
}

...并在处理播放器对象时调用 Dispose