1

I've got a Picturebox, which the user can drag up or down.

The program in question is a complex music staff editor for a piano, and thus the only way to achieve the moving of notes on a staff is with a number of if-statements and by modifying co-ordinates.

The issue is that the user is unable to move the PictureBox component down, but when the object is dragged up, nothing happens. The class inherits from PictureBox.

I would just like to emphasise that the PictureBox works when dragged downwards, but does not move when dragged upwards. The dragging is done in intervals, i.e. the PictureBox can only be placed in certain places (hence the need for specific co-ordinates).

Dot NET
  • 4,891
  • 13
  • 55
  • 98
  • (unrelated: I would find your `Top` checks *much* easier to read if they were in [number-line order](http://stackoverflow.com/a/3188857/71059) - you may or may not agree) – AakashM Dec 20 '11 at 17:42
  • 2
    The snippet isn't good enough to diagnose it. The typical problem is that moving the control also changes the relative position of the mouse. – Hans Passant Dec 20 '11 at 17:44
  • The strange thing is that it works when I move the mouse down - it works PERFECTLY actually. But when I move the mouse up, it doesnt. And im using almost the same exact code for both situations. – Dot NET Dec 20 '11 at 17:46
  • You should post more code. Where are you attaching the `MouseMove` handler, for example? The code you posted only detaches it when button is released. Are you sure that you don't change `currentY` inside `OnDrag` (which is, btw, not a good name for a `MouseMove` handler)? Also, it's not clear where this code lives. Inside your `PictureBox`-derived class? Why are your handlers public? It is difficult to find the problem this way. And there are better ways to solve this than using a number of if-statements, but it's difficult to propose a solution when it's not entirely clear how it works. – vgru Dec 20 '11 at 18:39
  • @Groo I edited the code above to show the attaching of the handler. `currentY` is not changed in 'OnDrag', and this code lives inside my PictureBox derived class. – Dot NET Dec 20 '11 at 18:49
  • But the way your code is written right now, each time you move your mouse by a single pixel, the note will move by (say) 10px. Isn't it supposed to follow the pointer movement? Wouldn't something like this work better: `if (e.Y <= 158 && e.Y >= 148) { this.Top = 148; }`? – vgru Dec 20 '11 at 18:52
  • The way it's written now is exactly what I need :) The notes need to move by around 10px at a time. I didn't bother explaining this as it's unnecessary information which shouldn't have much of an implication on the question. But since you've asked, this is also why the if statements are used. Each note has a specific location and movement range. – Dot NET Dec 20 '11 at 19:06
  • I've update my answer to contain a corrected version of your code. – Lukasz M Dec 23 '11 at 08:47

1 Answers1

1

Your current solution may work sometimes, however the event can be invoked very often when you try to drag the control and snap it back to the coordinates you specified in if statements.

Suggested solution:

I would suggest you to use MouseMove event in the form or parent that contains the control you want to drag. The values should also be configurable, not hardcoded. The code would change only a little (comparing current mouse coordinates instead of control's Left and Top properties) and it should work correctly.

UPDATE:

I've corrected your code, so it now works allowing you to put a control in one of the three places (y equals to 138, 148 or 158). I change it only a bit not to require you to change a lot of code, but I strongly recommend you to use the first method described :).

    int currentY;
    bool isDragging = false;

    private void OnDrag(object sender, MouseEventArgs e)
    {
        if (isDragging)
        {
            //calculate Y position relative to parent
            int parentY = this.Top + e.Y;

            if (parentY < currentY)
            {
                if (parentY > 158 && parentY >= 148)
                {
                    if (this.Top != 148)
                    {
                        currentY += (this.Top - 148);
                        this.Top = 148;
                    }
                }
                else if (parentY < 148 /*&& parentY >= 138*/)
                {
                    if (this.Top != 138)
                    {
                        currentY += (this.Top - 138);
                        this.Top = 138;
                    }
                }

                //And so on

            }
            else if (parentY > currentY)
            {
                if (/*parentY <= 158 &&*/ parentY >= 148)
                {
                        currentY += (this.Top - 158);
                        this.Top = 158;
                }
                else if (parentY < 148 && parentY >= 138)
                {
                        currentY += (this.Top - 148);
                        this.Top = 148;
                }

                //And so on

            }
        }
    }

    public void MusicNote_MouseDown(object sender, MouseEventArgs e)
    {
        currentY = this.Top + e.Y;

        this.Capture = true;

        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            isDragging = true;
        }

        this.MouseMove += new MouseEventHandler(OnDrag);
    }

    public void MusicNote_MouseUp(object sender, MouseEventArgs e)
    {
        isDragging = false;

        this.Capture = false;

        this.MouseMove -= new MouseEventHandler(OnDrag);
    }

The previous solution would, however, work probably more as you want it to.

Lukasz M
  • 5,635
  • 2
  • 22
  • 29
  • Thanks for your reply! Could you kindly elaborate on the 'quick suggested solution'? Not sure if I understood exactly what you mean. – Dot NET Dec 20 '11 at 20:40
  • Tried this out, still having this problem. – Dot NET Dec 20 '11 at 22:30
  • Thanks for the assistance Lucas, unfortunately this did not work either. It's probably down to a defect with the PictureBox class. I'll still mark your answer for the effort - maybe it will help someone else in the future. Many thanks! – Dot NET Dec 23 '11 at 09:47
  • I've written a test application, use this code in it and it worked. Try to put the control in Location with y equals to 148 initially. Thanks for marking the answer :), but I still want to help you :). – Lukasz M Dec 23 '11 at 13:55
  • Thanks Lucas, I tried once again, however for some reason the dragging works when dragging down, but not when dragging up. WHen I try to drag up, nothing happens after the first level. Any idea? – Dot NET Dec 23 '11 at 14:14
  • Thanks for your help thus far. Unfortunately the deadline for this piece of code has arrived, so I'll see what I can do - probably going to try a different approach :) Many thanks once again. – Dot NET Dec 23 '11 at 14:43
  • In order to make it work it's important to use the code EXACTLY as I posted it. You should also post the control initially in Location with Top = 148. I used it in my test application, so I'm not sure why it doesn't work in your case. – Lukasz M Dec 23 '11 at 16:20