Search code examples
wpfvb.netcursor-positiononmousedownonmouseup

Make Object Follow Mouse On MouseDown and "Stick" On MouseUp


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.


Solution

  • 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 ;)