Make Object Follow Mouse On MouseDown and "Stick" On MouseUp
Asked Answered
P

3

2

I'm working with a project that is WPF and VB.net. I want to visually simulate "dragging" an object (though I do not want to use standard drag and drop for reason of purpose).

Basically, I have a label object that, on its MouseDown event, I want it to follow the mouse cursor inside a 640x480 solid-size grid (but not outside of it!). Mind you, this grid is centered inside a full-screen window. Again, the object should not follow the mouse outside of the grid (I'm guessing a "ClipToBounds = True" here)

Then, on the label's MouseUp event, I want it to either stay in its current position or return to its original position, as determined by the value of a boolean variable set by another object's MouseEnter property.

Note, if it would be easier to work with, I can change the grid to a canvas in a cinch. I'm guessing that would be desirable.

So, after that long-winded explanation, here is my question (two-fold):

  1. How do I make the object (label) follow the mouse cursor inside the grid/canvas, but not outside of it? This needs to happen on the MouseDown event of the label.

  2. How do I make the object "stick" in its current position? (From this, I can probably figure out how to make it return to its original position on my own. :D )

My upvote to whoever can help me accomplish this goal the most efficiently! Thank you all very much.

Propositus answered 14/4, 2011 at 6:7 Comment(0)
D
6

How about something like this :

XAML :

<Canvas x:Name="canv" ToolTip="tt one" Width="400" Height="400" Background="Blue">
    <Rectangle x:Name="rec" Fill="Red" Height="50" Width="50" MouseDown="Rectangle_MouseDown" MouseMove="Rectangle_MouseMove" MouseUp="Rectangle_MouseUp" />
</Canvas>

CODE-BEHIND :

    private bool isDragging;
    private void Rectangle_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        rec.CaptureMouse();
        isDragging = true;

    }

    private void Rectangle_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
    {
        if (isDragging)
        {
            Point canvPosToWindow = canv.TransformToAncestor(this).Transform(new Point(0, 0));

            Rectangle r = sender as Rectangle;
            var upperlimit = canvPosToWindow.Y + (r.Height / 2);
            var lowerlimit = canvPosToWindow.Y + canv.ActualHeight - (r.Height / 2);

            var leftlimit = canvPosToWindow.X + (r.Width / 2);
            var rightlimit = canvPosToWindow.X + canv.ActualWidth - (r.Width / 2);


            var absmouseXpos = e.GetPosition(this).X;
            var absmouseYpos = e.GetPosition(this).Y;

            if ((absmouseXpos > leftlimit && absmouseXpos < rightlimit)
                && (absmouseYpos > upperlimit && absmouseYpos < lowerlimit))
            {
                Canvas.SetLeft(r, e.GetPosition(canv).X - (r.Width / 2));
                Canvas.SetTop(r, e.GetPosition(canv).Y - (r.Height / 2));
            }
        }
    }

    private void Rectangle_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        rec.ReleaseMouseCapture();
        isDragging = false;
    }

This code could be enhanced, but I think you got the idea ;)

Deliver answered 14/4, 2011 at 8:9 Comment(3)
AWESOME!!!!!!! Just a note to anyone using this...make sure the object of whatever you are dragging on the canvas does NOT have the margin property set! Otherwise, you will have a rather drastic offset. :3Propositus
There is no problem about setting margins I guess neither for the canvas nor for the moving object, you just have to take them into account when calculating your colision values ;)Deliver
If they were used for positioning in a grid before the grid was changed to a canvas, then those margins will also throw off the point where the mouse is over the object while dragging, considerably, too. The positioning margin values don't do anything on a canvas to my knowledge, so it is best to just set them to "0".Propositus
P
1

Based on @Bruno's, this is my solution:

double maxX;
double maxY;

private void OnRectMouseDown(object sender, MouseButtonEventArgs e)
{
    maxX = canv.ActualWidth - rect.Width;
    maxY = canv.ActualHeight - rect.Height;

    rect.CaptureMouse();
    rect.MouseMove += OnRectMouseMove;
    rect.MouseUp += OnRectMouseUp;
}

private void OnRectMouseMove(object sender, MouseEventArgs e)
{
    var pos = e.GetPosition(canv);
    var newX = pos.X - (rect.Width / 2);
    var newY = pos.Y - (rect.Height / 2);

    if (newX < 0) newX = 0;
    if (newX > maxX) newX = maxX;

    if (newY < 0) newY = 0;
    if (newY > maxY) newY = maxY;

    rect.SetValue(Canvas.LeftProperty, newX);
    rect.SetValue(Canvas.TopProperty, newY);

    xVal.Content = (newX / maxX).ToString("F3");
    yVal.Content = (newY / maxY).ToString("F3");
}

private void OnRectMouseUp(object sender, MouseButtonEventArgs e)
{
    rect.ReleaseMouseCapture();
    rect.MouseMove -= OnRectMouseMove;
    rect.MouseUp -= OnRectMouseUp;
}
Perishable answered 21/8, 2013 at 15:16 Comment(0)
I
0

try this:

private void Form1_MouseClick(object sender, MouseEventArgs e)
{
    (name).Location = new Point(e.X,e.Y);
}

so that will make it so if you click the object will appear there

Indoxyl answered 27/8, 2013 at 17:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.