2

I have just finished a Minesweeper-game in Windows-Forms, which I did for practice.

Everything runs just fine, but I discovered, that if you click and hold a button, it will be unfolded, even if the mouse doesn't point to that button anymore.

Do you have a simple idea of how I could fix this?

The Code:

/// <summary>
/// Build up a new Gamefield with the number of buttons, the user has selected
/// </summary>
private void DrawGameField()
{
  _buttons = new Button[_xLength, _yLength];
  for (int yPos = 0; yPos < _yLength; yPos++)
  {
    for (int xPos = 0; xPos < _xLength; xPos++)
    {
      var btn = new Button()
      {
        Tag = new Point(xPos, yPos),
        Location = new Point(xPos * 30, yPos * 30),
        Size = new Size(30, 30),
      };

      _buttons[xPos, yPos] = (Button)btn;
      btn.MouseUp += btn_Click;
      _gamePanel.Controls.Add(btn);
    }
  }
}

/// <summary>
/// Is called when a field is left-clicked
/// </summary>
private void LeftMouseClick(object sender, MouseEventArgs e)
{
  var btn = sender as Button;
  Point pt = (Point)btn.Tag;

  // If there's already a flag on the field make it unclickable for left mouseclick
  if (btn.Image != null)
    return;

  _game.UnfoldAutomatically(pt.X, pt.Y);
  btn.Text = (_game.ReturnNumberInField(pt.X, pt.Y)).ToString();

  // If clicked field was not a bombfield
  if (btn.Text != "-1")
    UnfoldFields();

  else
    LooseGame();
}

Every button gets a mouseUp-event in the DrawGameField - Method. Every button also gets a Tag in that method, so it can be identified. LeftMouseClick is calles, as soon as the user (mouseUp)-clicks on one oft the gamefield-buttons.

I want to cancel that if the button on which the left mousebutton is released is different to the button, that was actually clicked on.

This should give the user the possibility, to change his mind...he might actually click on a field, then realizes, that he doesn't want to unfold that field, but in my solution he isn't able to undo his click yet....

kennyzx
  • 12,845
  • 6
  • 39
  • 83
christian
  • 110
  • 1
  • 2
  • 15

2 Answers2

2

Well Guys, with a little Help, I have the correct solution to the problem, which is as follows:

Use "MouseClick" and not "MouseUp" or "MouseDown".

Why?

MouseClick internally uses MouseDown then performs MouseCapture (notices, which control was under the mousepointer and checks, whether the mouse was still pointing to that control) if true -> click event if false -> return

The working code:

/// <summary>
/// Build up a new Gamefield with the number of buttons, the user has selected
/// </summary>
private void DrawGameField()
{
  // _xLength is the length of the field in x-direction
  // _yLength is the length of the field in y-direction
  var buttons = new Button[_xLength, _yLength];

  // Filling the buttonArray
  for (int yPos = 0; yPos < _yLength; yPos++)
  {
    for (int xPos = 0; xPos < _xLength; xPos++)
    {
      var btn = new Button()
      {
        Tag = new Point(xPos, yPos),
        Location = new Point(xPos * 30, yPos * 30),
        Size = new Size(30, 30)
      };
      // Apply a clickEvent to every button
      btn.MouseClick += Button_MouseClick; //first change here: Use MouseClick!!!
      buttons[xPos, yPos] = btn;
    }
  }
  AddGameButtonsToPanel(buttons);
}

/// <summary>
/// Adds Buttons to the gamepanel
/// </summary>
private void AddGameButtonsToPanel(Button[,] buttons)
{
  _buttons = buttons;
  _gamePanel.SuspendLayout();
  try
  {
    foreach (var btn in buttons)
      _gamePanel.Controls.Add(btn);
  }
  finally
  {
    _gamePanel.ResumeLayout();
  }
}

/// <summary>
/// Checks which mouse-button was clicked and calls the correct method for that button
/// </summary>
private void Button_MouseClick(object sender, MouseEventArgs e)
{
  // If it is the firs time a button is clicked, the stopwatch is started
  if (_firstClick)
    StartStopWatch();

  var btn = sender as Button;
  Point pt = (Point)btn.Tag;

  if (e.Button == MouseButtons.Left)
    Button_LeftClick(btn, pt);
  else
    Button_RightClick(btn, pt);
}
christian
  • 110
  • 1
  • 2
  • 15
0

You could create a variable on the form that is set on a MouseDown event. So on MouseDown you set the variable to the button tag of the clicked button.

Then on MouseUp you can compare he set value to the current sender tag value.

Brendan
  • 1,237
  • 1
  • 16
  • 34
  • This sounds like a pretty simple way, I will post my Solution as soon as this works..more ideas are stimm welcome ;) – christian Dec 19 '14 at 10:13
  • Ok, this wont work, as every mouseUp-event comes aftera mousedown... The activated control wont change with this solution. I somehow need to use mousecapture on my controls, has anyone an idea how to do that? – christian Dec 19 '14 at 10:57
  • Perhaps this assists: http://stackoverflow.com/questions/2411062/how-to-get-control-under-mouse-cursor – Brendan Dec 19 '14 at 11:43