在网格类中拖放时鼠标位置错误

时间:2013-12-31 16:58:34

标签: c# wpf .net-4.0 mousemove mouse-position

我基本上是在写一个简单的浮动面板,可以通过拖动它的标题栏(这是一个网格本身)来改变它的位置。但我无法让它发挥作用!似乎MouseEventArgs.GetPosition返回错误的观点。我在这里错过了什么?

public class FloatingPanel : Grid
    {
        Grid gridTitle;

        bool dragging = false;
        Point lastPos;

        public FloatingPanel(UserControl gadget)
        {
            this.MouseMove += FloatingPanel_MouseMove;

            gridTitle = new Grid();
            gridTitle.Height = 25;
            gridTitle.VerticalAlignment = System.Windows.VerticalAlignment.Top;
            gridTitle.Background = Brushes.Cyan;
            gridTitle.MouseLeftButtonDown += gridTitle_MouseLeftButtonDown;
            gridTitle.MouseLeftButtonUp += gridTitle_MouseLeftButtonUp;
            this.Children.Add(gridTitle);

            this.Height = gadget.Height + 25;
            this.Width = gadget.Width;

            gadget.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;
            this.Children.Add(gadget);
        }

        void gridTitle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            dragging = false;
        }

        void gridTitle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            lastPos = Mouse.GetPosition(this);
            dragging = true;
        }

        void FloatingPanel_MouseMove(object sender, MouseEventArgs e)
        {
            if(dragging)
            {
                Vector delta = e.GetPosition(this) - lastPos;
                this.Margin = new Thickness(this.Margin.Left + delta.X, this.Margin.Top + delta.Y, this.Margin.Right, this.Margin.Bottom);
                lastPos = e.GetPosition(this);
            }
        }
    }  

我也尝试使用System.Windows.Forms.Cursor.PositionSystem.Windows.Forms.Control.MousePosition来显示屏幕上的位置。但没有运气。
解决方案:问题通过3次修改解决(如Sphinxxx指出):
- 使用MouseEventArgs.GetPosition(null)代替MouseEventArgs.GetPosition(this)
- 使用mousedownmouseupMouse.Capture(gridTitle)Mouse.Capture(null)个事件中捕获和释放鼠标 - 设置网格的水平和垂直对齐方式。 (这对我来说似乎很奇怪。为什么点头设置对齐会导致问题?)

1 个答案:

答案 0 :(得分:2)

_MouseMove中,您尝试使用e.GetPosition(this)计算移动,但只能获得相对于Grid 的鼠标指针位置。您需要找到相对于其他UI元素的位置,例如包含Window以便知道网格应移动多少。

e.GetPosition(null)_MouseLeftButtonDown中尝试_MouseMove null 而不是)来计算正确{{1 }}第

本文阐述了不同之处: Getting the Mouse Position Relative to a Specific Element

编辑:更强大delta

在构造函数中,避免使用最终位于标题栏顶部的小工具,方法是将它们放在两个单独的FloatingPanel中(并让WPF句柄宽度和高度):

RowDefinition

public FloatingPanel(FrameworkElement gadget) { gridTitle = new Grid(); gridTitle.Height = 25; gridTitle.Background = Brushes.Cyan; gridTitle.MouseLeftButtonDown += gridTitle_MouseLeftButtonDown; gridTitle.MouseMove += gridTitle_MouseMove; gridTitle.MouseLeftButtonUp += gridTitle_MouseLeftButtonUp; //Create two grid rows - one to hold the title bar.. this.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto }); Grid.SetRow(gridTitle, 0); this.Children.Add(gridTitle); //..and one two hold the gadget: this.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto }); Grid.SetRow(gadget, 1); this.Children.Add(gadget); } / ..ButtonDown处理程序中,使标题栏“捕获”(并释放)鼠标移动,以便鼠标指针在移动速度过快时不会“滑落”:

..ButtonUp

编辑2:没有void gridTitle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { //Relese a previous capture: Mouse.Capture(null); dragging = false; } void gridTitle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { lastPos = Mouse.GetPosition(null); //Capture the mouse to ensure we get all future mouse movements: Mouse.Capture(gridTitle); dragging = true; } 的替代方案:

Mouse.Capture()