【问题标题】:Get mouse position at all times when dragging拖动时始终获取鼠标位置
【发布时间】:2015-12-02 16:02:22
【问题描述】:

我想在拖动时鼠标移动时获取鼠标位置。

这是我最小的不工作示例:

MainWindow.xaml:

<Window x:Class="WpfApplication8.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Canvas x:Name="_canvas" Background="Green">
        <TextBlock x:Name="_positionTextBlock"/>
        <Rectangle x:Name="_dragSource"
                   Width="20"
                   Height="50"
                   Fill="Blue" 
                   Canvas.Top="150" 
                   Canvas.Left="20" 
                   PreviewMouseDown="DoDrag"/>
        <Rectangle x:Name="_dragTarget"
                   Width="60" 
                   Height="70"
                   Fill="Red" 
                   Canvas.Top="110" 
                   Canvas.Left="300" 
                   AllowDrop="True"/>
    </Canvas>
</Window>

MainWindow.xaml.cs:

using System.Windows;
using System.Windows.Input;

namespace WpfApplication8
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void DoDrag(object sender, MouseButtonEventArgs e)
        {
            DragDrop.DoDragDrop(_dragSource, "abc", DragDropEffects.Move);
        }
    }
}

如您所见:我有一个名为 _positionTextBlockTextBlock,它应该在拖动时显示当前鼠标位置。

编辑(长篇大论):我有一个可以拖放到红色矩形上的绿色矩形。我的要求是,在拖动绿色矩形时显示鼠标位置。

我该怎么做?

我尝试过的:

MainWindow的构造函数改为:

public MainWindow()
{
    InitializeComponent();
    DragOver += (s, e) => _positionTextBlock.Text = e.GetPosition(_canvas).ToString();
}

但这只会显示鼠标在红色矩形上时的位置。

我也试过了:

public MainWindow()
{
    InitializeComponent();
    MouseMove += (s, e) => _positionTextBlock.Text = e.GetPosition(_canvas).ToString();
}

但是MouseMove-Event 在拖动时不会触发

我也试过了:

private void DoDrag(object sender, MouseButtonEventArgs ev)
{
    _dragSource.GiveFeedback +=
        (s, e) => _positionTextBlock.Text = Mouse.PrimaryDevice.GetPosition(_canvas).ToString();
    DragDrop.DoDragDrop(_dragSource, "abc", DragDropEffects.Move);
}

但这似乎获得了屏幕坐标中的窗口位置。

这就是我卡住的地方。有人知道吗?

【问题讨论】:

  • 尝试 QueryContinueDrag 事件。
  • 我试过了,但是有,比如GiveFeedback 事件,没有GetPosition()

标签: wpf drag-and-drop position mouse drag


【解决方案1】:

我试了一下你的demo,发现如果你在window上设置AllowDrop="True"DragOver事件就可以了。

如果要避免掉到窗口,可以监听窗口的 PreviewDragOver 事件。然后将DragEventArgs.Effect 设置为None,将DragEventArgs.Handled 设置为True。

您也可以通过其他方式获取鼠标位置,该方法一直有效,但您需要一个计时器来定期刷新位置。

Visual.PointFromScreen(MousePositionToScreen);

public Point MousePositionToScreen
{
    get
    {
        GetCursorPos(out POINT p);
        return new Point(p.X, p.Y);
    }
}

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

    public POINT(int x, int y)
    {
        this.X = x;
        this.Y = y;
    }
}

[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool GetCursorPos(out POINT pt);

最后,你可以试试Keith Stein's solution。这要复杂得多。

【讨论】:

    【解决方案2】:

    使用 PreviewMouseMove 编辑

    第二次编辑:完整示例

    XAML:

    <Canvas x:Name="_canvas" Background="Green">
        <TextBlock x:Name="_positionTextBlock"/>
        <Rectangle x:Name="_dragSource"
                   Width="20"
                   Height="50"
                   Fill="Blue" 
                   Canvas.Top="150" 
                   Canvas.Left="20" 
                   PreviewMouseMove="DragSourcePreviewMouseMove"/>
        <Rectangle x:Name="_dragTarget"
                   Width="60" 
                   Height="70"
                   Fill="Red" 
                   Canvas.Top="110" 
                   Canvas.Left="300" 
                   AllowDrop="True"/>
    </Canvas>
    

    代码隐藏:

    public MainWindow()
    {
        InitializeComponent();
    }
    
    private void DragSourcePreviewMouseMove(object sender, MouseEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            _positionTextBlock.Text = e.GetPosition(_canvas).ToString();
        }
        e.Handled = true;
    }
    

    希望这会有所帮助。

    【讨论】:

    • 为什么会这样?您已在事件处理程序中添加了 if。但问题是,该事件不会触发。因此事件处理程序没有被调用! (忽略这个事实,这不会编译......)
    • @Rico-E 我编辑它以使用 PreviewMouseMove,它对我有用。还记得将事件标记为已处理。
    • 它对我不起作用。 PreviewMouseMove-event 不会被触发,因此处理程序永远不会被调用。
    • 奇怪,我自己使用你自己的 xaml 验证了它,它可以工作。我只删除了'PreviewMouseDown="DoDrag"'。 (实际上,您可以删除两个矩形进行测试)。发布您测试的代码。
    • 你删除了`PreviewMouseDown="DoDrag"`?你在跟我开玩笑吗?这是最重要的部分!我想在拖动时获得鼠标位置
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-02
    • 2017-07-29
    • 1970-01-01
    • 2010-10-29
    • 2013-05-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多