将DragMove锁定在区域内|只有水平垂直运动| DragMove预览事件

时间:2017-05-09 07:58:14

标签: c# wpf

我有一个WindowContainer课程,其中所有ChildWindows都会自动注册。我们的想法是,所有ChildWindows都被“锁定”在WindowContainer内,您无法将其移动/拖动到此区域之外。

ChildWindow继承自Window

我已经找到了解决方案:

C#Snippet

// Events

private void ChildWindow_OnLocationChanged(object sender, EventArgs eventArgs)
{
    _CheckBounds(sender as HtChildWindow);
}

private void ChildWindow_OnSizeChanged(object sender, SizeChangedEventArgs sizeChangedEventArgs)
{
    _CheckBounds(sender as HtChildWindow);
}

// Private Methods

private void _CheckBounds(HtChildWindow window)
{
    Rect trueWindowContainer = WindowContainer.TransformToAncestor(System.Windows.Application.Current.MainWindow).TransformBounds(new Rect(new Point(0, 0), WindowContainer.RenderSize));

    if (window.Left < trueWindowContainer.X)
        window.Left = trueWindowContainer.X;
    if (window.Top < trueWindowContainer.Y)
        window.Top = trueWindowContainer.Y;
    if (window.Left + window.ActualWidth > trueWindowContainer.X + trueWindowContainer.Width)
        window.Left = (trueWindowContainer.X + trueWindowContainer.Width) - window.ActualWidth;
    if (window.Top + window.ActualHeight > trueWindowContainer.Y + trueWindowContainer.Height)
        window.Top = (trueWindowContainer.Y + trueWindowContainer.Height) - window.ActualHeight;            
}

问题是,Window仍然可以移动到该区域之外并且它是滞后的。我想通过锁定垂直或水平移动来避免这种行为。

我的解决方案方法是抓住PreviewMouseMovePreviewDragMove事件。但我不知道该怎么做。 PreviewDragMove不存在。

预览

preview

最终工作解决方案

ChildWindow

    // ##############################################################################################################################
    // Properties
    // ##############################################################################################################################

    /// <summary>
    /// True when when mouse is down on the dragmove area
    /// </summary>
    public bool IsMouseDownOnDrag { get; private set; }

    private Rectangle _PartDragMove;
    private Point _AnchorPoint;
    private bool _IsDragging;
    private Rect _DragMoveArea = Rect.Empty;

    // ##############################################################################################################################
    // Konstructor
    // ##############################################################################################################################

    private HtChildWindow()
    {
        Unloaded += _OnUnloaded;
        Loaded += _OnLoaded;
    }

    private void _OnLoaded(object sender, RoutedEventArgs routedEventArgs)
    {
        if(_DragMoveArea == Rect.Empty)
            _DragMoveArea = SystemParameters.WorkArea;
    }

    private void _OnUnloaded(object sender, RoutedEventArgs routedEventArgs)
    {
        if (_PartDragMove != null)
        {
            _PartDragMove.PreviewMouseLeftButtonDown -= PartDragMove_OnPreviewMouseLeftButtonDown;
        }
    }

    // ##############################################################################################################################
    // Overrides
    // ##############################################################################################################################

    public override void OnApplyTemplate()
    {
        _PartDragMove = GetTemplateChild("PART_DragMove") as Rectangle;
        if (_PartDragMove != null)
        {
            _PartDragMove.PreviewMouseLeftButtonDown += PartDragMove_OnPreviewMouseLeftButtonDown;
        }

        base.OnApplyTemplate();
    }

    protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
    {
        if (IsMouseDownOnDrag)
        {
            _AnchorPoint = PointToScreen(e.GetPosition(this));
            _IsDragging = true;
            CaptureMouse();
            e.Handled = true;
        }
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        if (_IsDragging)
        {
            Point currentPoint = PointToScreen(e.GetPosition(this));

            double newLeftPosition = Left + currentPoint.X - _AnchorPoint.X;
            double newTopPosition = Top + currentPoint.Y - _AnchorPoint.Y;

            //control area
            if (newLeftPosition < _DragMoveArea.X)
                newLeftPosition = _DragMoveArea.X;
            if (newTopPosition < _DragMoveArea.Y)
                newTopPosition = _DragMoveArea.Y;
            if(newLeftPosition + ActualWidth > _DragMoveArea.X + _DragMoveArea.Width)
                newLeftPosition = _DragMoveArea.X + _DragMoveArea.Width - ActualWidth;
            if (newTopPosition + ActualHeight > _DragMoveArea.Y + _DragMoveArea.Height)
                newTopPosition = _DragMoveArea.Y + _DragMoveArea.Height - ActualHeight;

            Left = newLeftPosition;
            Top = newTopPosition;
            _AnchorPoint = currentPoint;
        }
    }

    protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
    {
        IsMouseDownOnDrag = false;
        if (_IsDragging)
        {
            _IsDragging = false;
            e.Handled = true;
            ReleaseMouseCapture();
        }
    }

    // ##############################################################################################################################
    // Events
    // ##############################################################################################################################

    private void PartDragMove_OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs mouseButtonEventArgs)
    {
        IsMouseDownOnDrag = true;
    }

    // ##############################################################################################################################
    // Public Methods
    // ##############################################################################################################################

    public void SetDragMoveArea(Rect area)
    {
        _DragMoveArea = area;
    }

所以现在我只是在我的SetDragMoveArea()ChildWindow 已锁定时才调用WindowContainer。 我正在使用以下代码提取该区域的信息

WorkingArea = WindowContainer.TransformToAncestor(System.Windows.Application.Current.MainWindow).TransformBounds(new Rect(new Point(0, 0), WindowContainer.RenderSize));

默认情况下,它是否锁定在Screen内(请参阅_OnLoaded)。

工作解决方案的预览

Working_Preview

1 个答案:

答案 0 :(得分:1)

我找到了适合你的解决方案。如果要自定义移动,则无法使用DragMove方法。相反,您必须自己实现此功能,覆盖以下三个功能:OnMouseLeftButtonDownOnMouseMoveOnMouseLeftButtonUp。 我已经实现了类似的东西:

 protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            anchorPoint = e.GetPosition(this);
            inDrag = true;
            CaptureMouse();
            e.Handled = true;
        }

anchorPoint是我用于Binging窗口位置的点,inDrag是私有布尔值,CaptureMouseUIElement方法。

然后:

    protected override void OnMouseMove(MouseEventArgs e)
    {
        if (inDrag)
        {
            Point currentPoint = e.GetPosition(this);
            this.Left = this.Left + currentPoint.X - anchorPoint.X;
            /*this.Top = this.Top + currentPoint.Y - anchorPoint.Y*/; // this is not changing in your case
            anchorPoint = currentPoint;
        }
    }

    protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
    {
        if (inDrag)
        {
            ReleaseMouseCapture();
            inDrag = false;
            e.Handled = true;
        }
    }

其中ReleaseMouseCaptureUIElement方法。 我认为它应该对你有帮助。