Получение и чтение события KeyEventArgs для класса, отличного от Form - PullRequest
2 голосов
/ 12 апреля 2019

В настоящее время я работаю над небольшой игрой в качестве проекта WinForms. Игровое поле построено из сетки тайлов, по которой может двигаться игрок (отдельный класс). Я хочу, чтобы игрок двигался с помощью клавиш со стрелками и настроил для него обработчик событий, но он, кажется, никогда не вызывается.

(минимизированный) класс проигрывателя, который реализует пакеты System.Windows.Forms для KeyEventArgs:

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 в C # , кажется, просто говорит this.KeyDown += ReadKeyDown;, но он не распознает KeyDown как что-либо и не дает мне возможную отсутствующую ссылку на сборку.

Ответы [ 2 ]

1 голос
/ 12 апреля 2019

KeyDown является членом Control, поэтому в вашем случае вы можете подписаться на это событие в своем 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

Теперь, что вы могли бы сделать, это вызвать метод в вашем целевом классе, как только вы получили такое событие:

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);
    }
}
0 голосов
/ 12 апреля 2019

Вы можете подписаться на событие 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 метод, подобный следующему:

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

... и вызов Dispose всякий раз, когда вы располагаете объект игрока.

...