3

I tried the dragOver event handler but it didn't work as it should.

I am working on a piano and I want to be able to play the note even if the mousedown didn't happen on that key.

Is there an event handler for this?

The below is a picture of the piano I am working on.

Piano

napi15
  • 2,354
  • 2
  • 31
  • 55
Kurt Camilleri
  • 133
  • 1
  • 1
  • 11
  • outside the button? can you be more clear? – napi15 Nov 17 '17 at 14:37
  • if I click on button1 and then (with the mouse still down) I drag over to button2. I would like to play the sound of button2 as well. Is there an event for this? – Kurt Camilleri Nov 17 '17 at 14:41
  • @KurtCamilleri Would like to see if you got my answer to work for you. My testing and output shows it fully functional. – Blake Thingstad Nov 17 '17 at 15:55
  • It makes for awkward UI, but it is possible. The key is to let a click behave like a click and make a special case for a drag. Which requires using the MouseMove event so you can see the user trying to drag the mouse while holding down the left mouse button. Sample code [is here](https://stackoverflow.com/a/14732877/17034). Whether this is something you actually want to do for playing a piano is pretty doubtful. You probably want to set the Capture property back to false so you'll get MouseMove events for other keys. – Hans Passant Nov 17 '17 at 17:28

3 Answers3

1

You should be able to watch for Mouse Enter and then check the Mouse state to see if it's clicked

private void object_MouseEnter(object sender, EventArgs e) 
{
    if (Mouse.LeftButton == MouseButtonState.Pressed)
    {
        'Do Something
    }
}
SteveB
  • 894
  • 7
  • 15
1

Yes you're trying to click and drag like here :

private void MyMouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left && e.Clicks == 1)
            {
               //Bla bla bla , do whatever you want 
            }
        }
napi15
  • 2,354
  • 2
  • 31
  • 55
0

When the MouseUp event goes off, you can check if the mouse is over another button. If it is, then perform a click on that button. I took the GetCursorPosition code from an answer in this question.

Had to put true and false into button tags to be able to tell if the ButtonClick was already handled for that button or not.

// running as Console window
// output from...
// 1. clicking and releasing on button1
// 2. clicking and holding on button1 and then releasing not over button1 or button2,
// 3. clicking and holding on button1 and then 
// moving mouse to over button2 and releasing mouse.

// button1 Click
// button1 Ding!
// button1 MouseUp
// button1 MouseUp
// button1 Ding!
// button1 MouseUp
// button1 Ding!
// button2 Click
// button2 Ding!

private List<Button> _buttons { get; set; }

public Form1()
{
    InitializeComponent();

    button1.MouseUp += Button_MouseUp;
    button2.MouseUp += Button_MouseUp;

    button1.Click += Button_Click;
    button2.Click += Button_Click;

    button1.Tag = false;
    button2.Tag = false;

    _buttons = new List<Button>()
    {
        button1, button2
    };
}

private void Button_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
    var button = sender as Button;
    Console.WriteLine($"{button.Text} MouseUp");
    if (!(bool)button.Tag)
        ButtonClick(button);
    else
        button.Tag = false;

    Func<Button, bool> ContainsMouse = (b) =>
    {
        var rect = b.RectangleToScreen(b.DisplayRectangle);
        var pos = GetCursorPosition();
        return rect.Contains(pos.X, pos.Y);
    };

    var hoverButton = _buttons.SingleOrDefault(b => ContainsMouse(b));
    if (hoverButton != null && !hoverButton.Equals(button))
        hoverButton.PerformClick();
}

private void Button_Click(object sender, EventArgs e)
{
    var button = sender as Button;
    Console.WriteLine($"{button.Text} Click");
    ButtonClick(button);
    button.Tag = true;
}

private void ButtonClick(Button button)
{
    Console.WriteLine($"{button.Text} Ding!");
}

[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
    public int X;
    public int Y;

    public static implicit operator Point(POINT point)
    {
        return new Point(point.X, point.Y);
    }
}

/// <summary>
/// Retrieves the cursor's position, in screen coordinates.
/// </summary>
/// <see>See MSDN documentation for further information.</see>
[DllImport("user32.dll")]
public static extern bool GetCursorPos(out POINT lpPoint);

public static Point GetCursorPosition()
{
    POINT lpPoint;
    GetCursorPos(out lpPoint);
    //bool success = User32.GetCursorPos(out lpPoint);
    // if (!success)

    return lpPoint;
}
Blake Thingstad
  • 1,639
  • 2
  • 12
  • 19
  • Thank you, however this works after the left button up button happens. I wanted something to work when I hover over the next button, so that that button can pressed immediately. @Blake – Kurt Camilleri Nov 17 '17 at 20:01
  • @KurtCamilleri Can you be more specific in what it needs to do? I'm not quite sure what you mean. I was imagining the purpose of this was to be able to play two keys at the same time. – Blake Thingstad Nov 17 '17 at 20:45
  • @KurtCamilleri Is the following description accurate? Click and hold on button1 so it "Dings!" on MouseDown, then drag to button2 and release so that it "Dings!" on MouseUp? Btw, if that is accurate, I'm not sure that's intuitive. As a user, I wouldn't guess that that would happen. – Blake Thingstad Nov 17 '17 at 20:48