давая классы клик события C # - PullRequest
2 голосов
/ 29 декабря 2010

Привет, мне просто интересно, есть ли способ дать классам свое собственное событие клика. Например, у меня есть класс карты, и есть ли способ узнать, когда пользователь нажимает на прямоугольник (отображающий изображение карты) из этого класса?

или, еще лучше, как узнать, когда щелкают по прямоугольнику карт?

Ответы [ 3 ]

7 голосов
/ 29 декабря 2010

Чтобы получать сообщения "щелкнули мышью здесь" из Windows, вам нужно иметь дескриптор окна; в WinForms все, что происходит от Windows.Forms.Control, будет иметь дескриптор окна и получать сообщения мыши. Эти сообщения будут автоматически переведены в вызовы событий .NET MouseDown, MouseUp, MouseClick и т. Д.

Так что, вероятно, ваша карта должна быть контрольной. Если это не так (например, если у вас есть элемент управления «Рука», который отвечает за управление и вытягивание большого количества карт), то этот элемент управления должен быть тем, который получает события мыши (например, MouseClick) и выясняет, какая карта фактически была нажата на основе контекст и координаты события мыши.

3 голосов
/ 29 декабря 2010

На самом деле есть две части вашей проблемы: первая - создание события, а вторая - его подключение к чему-либо.

Создание события является простой частью:

public class Card {
    public event EventHandler<MouseEventArgs> Click;
    protected void OnClick(MouseEventArgs e) {
        EventHandler<MouseEventArgs> handler = Click;
        if(handler != null) {
            handler(this, e);
        }
    }

    internal void CheckIfClicked(MouseEventArgs e) {
        if(/* this mouse event intersects this Card */) {
            OnClick(e);
        }
    }
}

Тогда в других местах вы можете настроить подписчиков для этого события, как обычно:

public class CardWatcher {
    private Card card;

    public CardWatcher(Card card) {
        this.card = card;
        this.card.Click += card_Clicked;
    }

    private void card_Clicked(object sender, MouseEventArgs e) {
        // Our Card has been clicked; do something about it
    }
}

(Обратите внимание, что мы подключаем обработчик событий вручную, но это почти такой же код, который конструктор Visual Studio сгенерировал бы, если бы вы использовали графический интерфейс для присоединения обработчика событий к элементу управления.)

И затем вам нужно где-то зафиксировать эти события щелчка (на самом деле, это похоже на суть вашей проблемы):

public partial class CardContainer : UserControl {
    private List<Card> cards = new List<Card>();

    public CardContainer() {
        InitializeComponent();

        // Initialize cards here...
    }

    protected override void OnMouseUp(MouseEventArgs e) {
        foreach(Card card in cards) {
            card.CheckIfClicked(e);
        }
        base.OnMouseUp(e);
    }
}

Обратите внимание, что обычно существует два способа реагирования на событие:

  1. Создайте класс подкласса и переопределите поведение OnEvent метода
  2. Присоединить делегат обработчика событий

Как указали другие ответы, операционная система Windows заботится о доставке событий объектам, которые являются окнами (то есть объектам, имеющим дескриптор окна). В .NET это означает объекты, которые являются подклассами Control.

Достаточно просто создать такие классы самостоятельно, либо путем подкласса Control напрямую, либо путем подкласса чего-то вроде UserControl, что затем позволяет создавать элементы управления, которые могут быть контейнерами для других элементов управления, которые вы создаете в представлении конструктора ( так же, как вы создаете формы).

Итак, ваш выбор следующий:

  • Сделать Card элементом управления; затем его можно размещать в формах и напрямую получать события щелчка (и другие события). Недостатком является то, что это может использовать много ресурсов, если у вас много активных элементов одновременно, поскольку каждый выделяет дескриптор окна из Windows.
  • Создайте контейнер для Card s, который является контрольным. Этот контейнерный элемент управления можно размещать в формах и напрямую получать события щелчка (и другие события). Недостаток заключается в том, что вы должны вручную выяснить, как делегировать эти события щелчка по отдельным карточкам. Поскольку фактическое событие Click не несет с собой координат, вам, вероятно, придется обрабатывать событие MouseUp.
  • Поместите ваши Card s в другой контейнер (например, Form) и прикрепите обработчик к событию Click (или MouseUp) этого контейнера. В этом обработчике выясните, были ли нажаты какие-либо из ваших Card, и соответственно делегируйте события щелчка.

Обратите внимание, что все это не зависит от того, есть ли у Card событие Click, на которое могут подписаться пользователи Card. Если вы посмотрите на первый пример кода в этом ответе, то нет причины, по которой метод CheckIfClicked в Card должен фактически запускать реальное событие, если у вас нет таких классов, как CardWatcher, которые заинтересованы в знании событий click на Card s. Если только событие Card когда-либо заботится о событии click, то вы можете просто создать метод, такой как Card.HasBeenClicked(MouseEventArgs e), поместить туда код обработки кликов и позволить CheckIfClicked вызывать его напрямую.

1 голос
/ 29 декабря 2010

Вы можете легко добавлять события в свой класс, но единственный способ, которым класс может узнать, когда что-то было щелкнуто, - это когда это происходит или имеет компонент на основе окна.для.Если вам нужно написать класс, который может обнаруживать такие события, я бы порекомендовал создать элемент управления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...