Сделать так, чтобы объект следовал за мышью при нажатии на MouseDown и закреплялся при перемещении мыши

Я работаю с проектом WPF и VB.net. Я хочу визуально имитировать «перетаскивание» объекта (хотя я не хочу использовать стандартное перетаскивание по причинам определенной цели).

По сути, у меня есть объект метки, который в своем событии MouseDown я хочу, чтобы он следовал за курсором мыши внутри сплошной сетки размером 640x480 (но не за ее пределами!). Имейте в виду, что эта сетка центрируется внутри полноэкранного окна. Опять же, объект не должен следовать за курсором мыши за пределами сетки (я предполагаю, что здесь "ClipToBounds = True")

Затем в событии MouseUp метки я хочу, чтобы он либо оставался в своей текущей позиции, либо возвращался в исходное положение, что определяется значением логической переменной, установленной свойством MouseEnter другого объекта.

Обратите внимание: если с этим будет проще работать, я могу легко изменить сетку на холст. Я предполагаю, что это было бы желательно.

Итак, после этого пространного объяснения, вот мой вопрос (двоякий):

  1. Как заставить объект (метку) следовать за курсором мыши внутри сетки / холста, но не за ее пределами? Это должно произойти в событии MouseDown метки.

  2. Как мне заставить объект «застрять» в его текущем положении? (Из этого я, вероятно, смогу выяснить, как вернуть его в исходное положение самостоятельно .: D)

Я выражаю поддержку тем, кто может помочь мне достичь этой цели наиболее эффективно! Всем большое спасибо.


person CodeMouse92    schedule 14.04.2011    source источник


Ответы (3)


Как насчет чего-то вроде этого:

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>

КОД ЗА:

    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;
    }

Этот код можно было бы улучшить, но я думаю, вы уловили идею;)

person Bruno    schedule 14.04.2011
comment
КЛАССНО!!!!!!! Просто примечание для всех, кто использует это ... убедитесь, что объект того, что вы перетаскиваете на холст, НЕ имеет установленного свойства поля! В противном случае у вас будет довольно резкий зачет. : 3 - person CodeMouse92; 17.04.2011
comment
Нет проблем с установкой полей, я думаю, ни для холста, ни для движущегося объекта, вам просто нужно принять их во внимание при вычислении значений коллизии;) - person Bruno; 18.04.2011
comment
Если они использовались для позиционирования в сетке до того, как сетка была заменена на холст, то эти поля также будут значительно отличаться от точки, в которой указатель мыши находится над объектом при перетаскивании. Насколько мне известно, значения поля позиционирования ничего не делают на холсте, поэтому лучше всего просто установить их на 0. - person CodeMouse92; 18.04.2011

Основываясь на @ Bruno, это мое решение:

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;
}
person MicBig    schedule 21.08.2013

попробуй это:

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

так что если вы щелкнете, объект появится там

person djhd    schedule 27.08.2013