MouseUp и MouseDown всегда имеют одного и того же отправителя объекта

Я пытаюсь создать клон сапера, и у меня проблемы с мышью. Если я нажимаю кнопку мыши на графическом блоке, а затем перемещаю мышь в другое поле, событие mouseup по-прежнему будет иметь тот же отправитель объекта, даже если это произойдет в другом элементе управления.

Мне нужно событие mousedown, чтобы я мог видеть, были ли нажаты обе кнопки мыши, к сожалению, событие mouseup, похоже, не заботится о том, где находится курсор, когда я отпускаю кнопку.

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

У кого-нибудь есть идеи?


person Lito    schedule 18.04.2014    source источник
comment
Мышь захватывается Control, на котором произошло MouseDown.   -  person Dmitry    schedule 19.04.2014
comment
Да, проблема в том, что должен быть какой-то способ реализовать ту же механику мыши, что и в оригинальном сапере.   -  person Lito    schedule 19.04.2014
comment
Исходный MineSweeper не использовал элементы управления для каждой плитки. Его просто нарисовали.   -  person LarsTech    schedule 19.04.2014
comment
Возможно, мне следует просто проверить местоположение щелчка и вычислить, какая плитка была нажата, и не беспокоиться о событиях для определенных элементов управления.   -  person Lito    schedule 19.04.2014


Ответы (4)


Мне удалось придумать кое-что, что поможет, я оставлю это здесь, если это понадобится кому-то еще в будущем.

private void MouseUp(object sender, MouseEventArgs e)
    {
        Point ptCursor = Cursor.Position;
        ptCursor = PointToClient(ptCursor);
        PictureBox pBox = (PictureBox)GetChildAtPoint(ptCursor);
        pBox.BackColor = System.Drawing.Color.Blue;
    } 

Я установил простую форму с некоторыми графическими блоками, и когда происходит событие mouseup, он проверяет элемент управления под позицией курсоров, и затем вы можете использовать это для своих нужд. Проблема, с которой я столкнулся, заключалась в том, что событие mouseup было привязано к элементу управления, где произошло событие mousedown, и поэтому я не мог получить доступ к элементу управления, в котором находился курсор, когда произошло событие mouseup.

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

person Lito    schedule 19.04.2014
comment
Я должен добавить, что вам также понадобится try-catch, так как он выйдет из строя, если вы отпустите кнопку мыши там, где нет окна с картинками. - person Lito; 19.04.2014
comment
Возможно, лучше явно проверить, что возврат GetChildAtPoint() - это PictureBox, например var pBox = GetChildAtPoint(ptCursor) as PictureBox; if (pBox != null) {…}, вместо использования блока try {…} catch {…}. - person binki; 29.07.2014

Лично я делаю это с помощью переменной Point уровня формы, которую я обновляю при каждом событии MouseMove. Затем, когда происходят другие события мыши, у них есть самые последние доступные события.

person Spizmar    schedule 18.04.2014
comment
Это означало бы, что мне нужно было бы вычислить, на каком элементе управления находится курсор, на основе координат курсора, верно? - person Lito; 19.04.2014
comment
да. Так что сделайте их 8 на пиксели или 16 на 16. Затем для 8 пикселей сделайте x = e.locations.X ›› 3; на 16, e.Location.X ›› 4; Он автоматически дает вам индекс. - person Spizmar; 19.04.2014

Я бы так сделал:

  1. Создайте подклассы кнопок, которые будут содержать игровые ресурсы в виде изображения.
  2. Создайте настраиваемый элемент управления и добавьте необходимое количество кнопок.
  3. При щелчке мышью я бы снова проверил Contains метод Bounds, чтобы узнать, произошел ли щелчок по этой конкретной кнопке, или другим способом обработать щелчок кнопки внутри настраиваемого элемента управления.

Было бы лучше, если бы мы увидели часть вашего кода и, возможно, снимок экрана.

Обновлять:

Это пример того, как обрабатывать щелчки с помощью делегатов.

public partial class MineSweeper : UserControl
{
    public MineSweeper()
    {
        InitializeComponent();
    }

    private void MineSweeper_Load(object sender, EventArgs e)
    {
        this.BackColor = Color.Red;
        for (int i = 0; i < 16; i++)
        {
            var button = new Button();
            button.Name = "Button" + i;
            button.Size = new Size(50, 50);
            button.ForeColor = Color.Yellow;

            button.ForeColor = Color.Black;
            button.Click += delegate
            {
                MessageBox.Show("You have clicked me! I am " + button.Name);
            };
            flowLayoutPanel1.Controls.Add(button);
            flowLayoutPanel1.Invalidate();
        }

        this.Invalidate();
    }
}

Просто добавьте новый UserControl из дизайнера, добавьте к нему flowLayoutPanel и установите для его свойства dock значение full.

person Saeid Yazdani    schedule 18.04.2014
comment
Ну, код очень разбросан на части, но я сделал то, что я создал сетку из графических блоков, которые я храню в массиве. Я храню то, что находится под каждой плиткой, в отдельном массиве. Я пробовал обрабатывать щелчки мыши с помощью событий mousedown и mouseup, но это вызывает некоторые проблемы, поскольку на самом деле они не работают так, как щелчки мыши в сапере. Мне нужно событие щелчка, которое проверяет, на каком элементе управления находится курсор при отпускании кнопки, а не там, где он был при первом нажатии. - person Lito; 19.04.2014
comment
Разве box.click не будет работать так же, как другое событие click в winforms? Основная проблема заключается в том, что мне нужен метод щелчка, который игнорирует, где произошло mousedown, и заботится только о том, где происходит moseup. - person Lito; 19.04.2014
comment
@Lito в этом случае просто замените Click на MouseUp. Я бы потратил немного времени и вставил немного кода и скриншотов ... Мне все еще трудно понять, что вам действительно нужно. - person Saeid Yazdani; 19.04.2014
comment
Я бы подумал, что FlowLayoutPanel будет неправильным типом контейнера для использования. Сапер представляет собой сетку. Застройщику необходимо иметь простой доступ к соседним плиткам во всех направлениях. Кстати, нет причин вызывать эти Invalidate() методы, если вы ничего не рисуете. - person LarsTech; 19.04.2014
comment
@LarsTech Вы совершенно правы, я просто использовал это, чтобы быстро привести кнопки в порядок. - person Saeid Yazdani; 19.04.2014
comment
Щелчок мышью начинается, когда вы нажимаете кнопку мыши, и заканчивается, когда вы ее отпускаете. Я хочу иметь возможность нажать кнопку мыши в одном элементе управления, отпустить ее в другом и привязать событие к тому месту, где я его отпускаю, а не к тому месту, где я сначала нажимаю на него. К сожалению, даже при использовании события mouseup он регистрирует элемент управления, в котором находится курсор, когда я впервые нажимаю на него, и не заботится о том, что я переместил курсор на другой элемент управления. - person Lito; 19.04.2014

[VS 2017 c #] Использование MouseEventArgs для положения мыши при нижнем / верхнем положении мыши работает только тогда, когда точка захватывается левой кнопкой мыши, как показано ниже.

private void Form1_MouseDown(object sender, MouseEventArgs e)
{
   //??? this changes at UP time and becomes same as MouseArgsUpPoint 
   //MouseArgsDownPoint = new Point(e.X, e.Y);
   //same as above, MouseArgsDownPoint = PointToClient(MousePosition);

   if (e.Button == MouseButtons.Left)
   {
       //inside here it works fine and Up/Down points are different and correct
       MouseArgsDownPoint = new Point(e.X, e.Y);
   }
}


private void Form1_MouseUp(object sender, MouseEventArgs e)
{
    MouseArgsUpPoint = new Point(e.X, e.Y);
}
person Meung Kim    schedule 24.03.2020